简体   繁体   中英

Calculate absolute position for d3 graph nodes

I have a d3 force layout. Each node in this force layout has a label, which is a <div> code(can have table inside) and should follow it all the time. I defined the <div> 's position to be absolute and set their position like this:

var updateNode = function() {
label_xOffset=10;
label_yOffset=10
this.attr("transform", function(d,i) {
    //this is where I set their position
    //d.num declare corresponding div in node_lables_divs array
    node_labels_divs[parseInt(d.num)].style("left",(d.x+label_xOffset)+"px").style("top",(d.y+label_yOffset)+"px");
    return "translate(" + d.x + "," + d.y + ")";
    });
}

function tick(e) {
     node.call(updateNode);
}

Everything is good now as long as I don't pan or zoom in my SVG. But I need those features too. So in my zoom function I handled it like this:

var zoomer = d3.behavior.zoom().scaleExtent([0.1,10]).
    x(xScale).
    y(yScale).on("zoom", redraw);
function redraw() {
    var translation=" translate(" + d3.event.translate[0] + "px,"+d3.event.translate[1]+"px)";
    d3.selectAll("div.node_lables_html").style("transform",translation)
                                        .style("-webkit-transform",translation)
                                        .style("-ms-transform",translation);
     //vis is the <g> tag that contains the whole nodes and links
     vis.attr("transform","translate(" + d3.event.translate + ")"+" scale(" + d3.event.scale + ")");
}

Now every thing good when I drag and pan the SVG. But it is very bad when I try to zoom in the SVG, lables are going in different direction and they are not following the nodes. I print out the d3.event.translate and it seems that it has different scale in times of zoom and panning. I also tried the d3 foreignElement but it seems that the transform attribute doesn't work for the foreignElements. How should I calculate the correct value to transform htmls?

As per this solution to a similar question (it's not a duplicate, quite), you need to:

  • Put the div into a foreignObject SVG element (which allows arbitrary HTML inside an SVG)
  • add the foreignObject to a group, along with anything else that needs to be with the label
  • Only apply the tranform s to the group

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM