如何使内部html元素与d3 js中的父元素一起拖动

时间:2014-03-11 10:18:58

标签: d3.js

下面是生成的html:

<g title="some" cx="308" cy="98">
   <circle class="node" cx="308" cy="98" r="20" style="stroke: gray; fill: white;">
   <text dx="298" dy="103">some</text>
</g>

当我拖动此元素时,只有外部g元素的cx和cy发生变化。圆圈和文字保持在同一位置。

我希望在拖动时将圆和文本与g元素一起拖动。

这是我的生成节点代码:

node = container.append("g").selectAll("svg.node")
                .data(json.nodes)
                .enter().append("g").call(drag);
            node.append("svg:circle")
                .attr("cx",function(nodeObj) { return (nodeObj.x);})
                .attr("cy",function(nodeObj) { return (nodeObj.y);})
                .attr("r", 20)
                .style("stroke", "gray")
                .style("fill", "white");
            node.append("text")
                .attr("dx",function(nodeObj) { return (nodeObj.x - 10);})
                .attr("dy",function(nodeObj) { return (nodeObj.y + 5);})
                .text(function(nodeObj) {return nodeObj.name;});
            node.attr("title",function(nodeObj) {return nodeObj.name;}); 

拖动行为:

        drag = d3.behavior.drag()
                .on("dragstart", dragstarted)
                .on("drag", dragmove)
                .on("dragend", dragended);

        dragmove = function (nodeObj) {
            nodeObj.x += d3.event.dx;
            nodeObj.y += d3.event.dy; 
            tick(); // this is the key to make it work together with updating both px,py,x,y on d !
        };

        dragstarted = function () {
           d3.event.sourceEvent.stopPropagation();
           d3.select(this).classed("dragging", true);
        };

        dragended = function (nodeObj) {
            if (d3.event.sourceEvent.which == 1){   
                  d3.select(this).classed("dragging", false);
                  tick();
            }
        };

        tick = function () {
            link.attr("x1", function(nodeObj) { return nodeObj.source.x; })
               .attr("y1", function(nodeObj) { return nodeObj.source.y; })
               .attr("x2", function(nodeObj) { return nodeObj.target.x; })
               .attr("y2", function(nodeObj) { return nodeObj.target.y; });

            node.attr("cx",function(nodeObj) { return (nodeObj.x);})
            node.attr("cy",function(nodeObj) { return (nodeObj.y);})

            force.stop();
        };

1 个答案:

答案 0 :(得分:1)

在SVG中,g元素没有cxcy属性 - 设置它们不会产生任何影响。您需要设置的是transform属性,例如到translate(<x>,<y>)。因此,更新节点位置的代码将是

node.attr("transform", function(nodeObj) {
  return "translate(" + nodeObj.x + "," + nodeObj.y + ")";
});

另请注意,力布局已经提供了拖动节点的工具,此外无需使用拖动行为:

container.call(force.drag);

参见例如this example