Search code examples
javascriptd3.jstopojson

d3js v5 + topojson v3 Center a square centroid with zoom


I try to put a square on the center of the geographical entity. I added orange circles to mark the position of the centroids.

With a scale extent = 1 (no zoom), the square's position is correct. enter image description here

However, with a scale extent > 1 (with zoom), there is a translation of the square's position. enter image description here

I assume the problem occurs when I define the square's position.

let ctrSquare = g.attr("class","ctr_square")
    .selectAll(".ctr_square")
    .data(featureCollectionZe.features)
    .enter()
    .append("rect")
    .attr("x", (d)=>{return path.centroid(d)[0] - 7/2;})
    .attr("y", (d)=>{return path.centroid(d)[1] - 7/2;})
    .attr("width",7)
    .attr("height",7)
    .attr("fill","#0000ff")
    .attr("stroke","#0000ff");

Here is my code : https://plnkr.co/edit/K0k9ACxFWgzsqzHmQHmM


Solution

  • The problem is that you want to keep rectangle size independent of current scale. So, during .on("zoom", ...) you modify the rects width and height:

    ctrSquare
        .attr("width",7/d3.event.transform.k)
        .attr("height",7/d3.event.transform.k);
    

    Taking that into account, the correct code for their x and y position is following:

    ctrSquare
        .attr("x",d => path.centroid(d)[0] - 7/d3.event.transform.k/2)
        .attr("y",d => path.centroid(d)[1] - 7/d3.event.transform.k/2)
    

    So just add these lines into .on("zoom", ...).