Maddy Chavda
Maddy Chavda

Reputation: 591

Semantic zoom on map with circle showing capital

I wanted to implement semantic zoom on map of d3.js. I have developed a example of map and Major cities of particular country, which is working fine but sometime circle got overlap due to near places in maps so if i implement semantic zoom which will solve my circle overlapping problem.

I don't understand how to transform only graph not circle in my map.

My zooming function code is :

var zoom = d3.behavior.zoom()
    .on("zoom",function() {
        g.attr("transform","translate("+ 
            d3.event.translate.join(",")+")scale("+d3.event.scale+")");
        g.selectAll("circle")
            .attr("d", path.projection(projection));
        g.selectAll("path")  
            .attr("d", path.projection(projection)); 

  });

My jsfiddle link

Anybody help me please!

Upvotes: 0

Views: 918

Answers (2)

Fernando
Fernando

Reputation: 43

I know this is an old post and it already has an accepted answer but as the original post suggests, d3's Semantic Zoom is a cleaner way of doing this. I implemented the same thing you did (circles on cities on a map) by following this demo https://bl.ocks.org/mbostock/368095. The only thing I had to change was I had to subtract the initial position of the circles in the transform function in order to correct their initial position.

  function transform(t) {
      return function(d) {
          const point = [d.x, d.y] // this is the initial point
          const tPoint = t.apply(point) // after translation
          const finalPoint = [tPoint[0] - d.x, tPoint[1] - d.y]// subtract initial x & y to correct 
          return `translate(${finalPoint})`;
  };

}

Upvotes: 0

Mark
Mark

Reputation: 108527

Are you asking how to not scale the circles according to the zoom? The way you have it you are scaling the g element and the circles are in it. The way I'd do it is to "shrink" the circles when zoomed.

// zoom and pan
var zoom = d3.behavior.zoom()
  .on("zoom",function() {
     g.attr("transform","translate("+ 
        d3.event.translate.join(",")+")scale("+d3.event.scale+")");
     g.selectAll("circle")
      .attr("r", function(){
        var self = d3.select(this);
        var r = 8 / d3.event.scale;  // set radius according to scale
        self.style("stroke-width", r < 4 ? (r < 2 ? 0.5 : 1) : 2);  // scale stroke-width
        return r;
    });
});

Update fiddle.

Upvotes: 7

Related Questions