D3.js版本4使节点粘滞

时间:2016-08-26 14:07:42

标签: javascript d3.js

我是D3版本4的新用户,我在向强制定向布局中添加固定节点功能时遇到了问题。我相信这是通过将d.fixed设置为true在v3中实现的,但是我将此问题转换为与v4兼容的问题。我已经尝试添加simulation.fix,但是如果不从模拟开始修复节点,就无法将其集成到我现有的代码中。

理想情况下,我想添加一个双击侦听器,它可以将节点固定到位,并允许它通过拖动功能定位,然后再次双击时恢复模拟力。提前感谢您的帮助。

这是我的js:

<!--load svg-->
<svg width="1500" height="600"></svg>
 <!--begin javascript for d3 forced layout-->
<script>
var svgNetwork = d3.select("svg"),
    width = +svgNetwork.attr("width"),
    height = +svgNetwork.attr("height");


var simulation = d3.forceSimulation()
    .force("link", d3.forceLink().id(function(data1) { return data1.id; }))
    .force("charge", d3.forceManyBody().strength(-1500))
    .force("center", d3.forceCenter(width / 2, height / 2));



//load  the node csv data and link csv data together - open node(open link(funtions for making chart))
d3.csv("nodes.csv", function (error1, data1) {
    if (error1) throw error1;
    console.log(data1);

    d3.csv("lines.csv", function (error2, data2) {
        if (error2) throw error2;
        console.log(data2);

        data1.forEach(function (data1){
            data1.group = +data1.group;
        });

        var lower = d3.min(data1, function(data1) {return data1.group;});
        var upper = d3.max(data1, function(data1) {return data1.group;});
        var color = d3.scaleLinear()
            .domain([lower, 0, upper])
            .range(["#2E64FE", "#E6E6E6", "red"]);


        var link = svgNetwork.append("g")
            .attr("class", "links")
            .selectAll("line")
            .data(data2)
            .enter()
                .append("line")
                .attr("stroke-width", function(data2) { return Math.sqrt(data2.value); })
            .attr("fill", "#777")
            .attr("stroke-opacity", "0.6");

    var node = svgNetwork.selectAll(".node")
         .data(data1)
             .enter()
                 .append("g");

        var circle = node.append("circle")
            .attr("id", function(data1) {return data1.id;})
            .attr("r", function(data1) {return data1.rad;})
            .attr("fill", function(data1) { return color(data1.group); })
            .style("stroke", function(data1) { return color(data1.group); })
            .style("stroke-width", "10px")
            .style("stroke-opacity", "0.9");    

        var label = node.append("svg:text")
            .text(function (data1) { return data1.id; })
            .style("text-anchor", "middle")
            .style("fill", "#000000")
            .style("font-family", "Arial")
            .style("font-size", "0.8em")
            .style("font-weight", "bold");

   node.call(d3.drag()
          .on("start", dragstarted)
          .on("drag", dragged)
          .on("end", dragended));


  simulation
      .nodes(data1)
      .on("tick", ticked);
  simulation.force("link")
      .links(data2);

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

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

        }

    });
});

function dragstarted(d) {
  if (!d3.event.active) simulation.alphaTarget(0.3).restart();
  d.fx = d.x;
  d.fy = d.y;
}

function dragged(d) {
  d.fx = d3.event.x;
  d.fy = d3.event.y;
}

function dragended(d) {
  if (!d3.event.active) simulation.alphaTarget(0);
  d.fx = null;
  d.fy = null;
}

以下是我的node.csv文件和lines.csv文件的示例:

node.csv

id  group   rad
a   0.168316947 0.288907878
b   -0.38499088 1.012210504
c   -0.548386797    1.301376974
d   -0.215565786    2.456429671
e   -0.756094177    6.409396582
f   -0.538867892    1.804950731
g   -0.325232806    0.518895927
h   0.686157994 1.011850971
i   -0.723155438    5.853700074
j   2.008089674 2.73207752
k   -0.358621917    2.040722107
l   -0.393305984    3.221637083
m   -0.676289998    1.598250699
n   -0.950808451    26.26021586
o   0.134589658 0.270633823
p   -0.521333199    6.216421369
q   1.628300116 2.293471337
r   0.62673 2
s   -0.843711093    40.86067523

lines.csv

source  target  value
b   a   20
c   a   20
d   a   20
e   a   20
f   a   20
g   a   20
h   a   20
i   a   20
j   a   20
k   a   20
l   a   20
m   a   20
n   a   20
o   a   20
p   a   20
q   a   20
r   a   20
s   a   20

2 个答案:

答案 0 :(得分:15)

不确定是否需要答案,但我能够使节点变得粘滞,实际上在您的代码中修复非常简单,我在GitHub上查看此问题时学到了它 - Issue #35

现在在d3库的v4中修复节点的想法非常简单,在上面的代码中只需注释两行:

function dragended(d) {
  if (!d3.event.active) simulation.alphaTarget(0);
  //d.fx = null;
  //d.fy = null;
}

理论是,为了修复节点,我们需要设置node.fx&amp;您的代码实际在node.fy函数定义中设置的dragged()

希望它对我有所帮助。

此处的文档中也提到了相同的内容 - D3 V4 - API

  

要将节点固定在给定位置,您可以指定另外两个节点   属性:

     
      
  • fx - 节点的固定x位置
  •   
  • fy - 节点的固定y位置
  •   

答案 1 :(得分:4)

另外,双击后释放节点的功能将是:

var node = g.selectAll(".nodes")
    .data(graph.nodes)
    .enter().append("g")
    .attr("class", "node")
    .style("fill", "black")

    // Next two lines -> Pin down functionality
    .on('dblclick', releasenode)
    .call(node_drag);

var node_drag = d3.drag()
    .on("start", dragstarted)
    .on("drag", dragged)
    .on("end", dragended);

function dragstarted(d) {
    if (!d3.event.active) simulation.alphaTarget(0.3).restart();
    d.fx = d.x;
    d.fy = d.y;
}

function dragged(d) {
    d.fx = d3.event.x;
    d.fy = d3.event.y;
}

function dragended(d) {
    if (!d3.event.active) simulation.alphaTarget(0);
    // Allows NODE FIXING
    // d.fx = null;
    // d.fy = null;
}
function releasenode(d) {
    d.fx = null;
    d.fy = null;
}