【问题标题】:Adding Multiple shaped nodes to a force directed network diagram in d3v4将多个形状节点添加到 d3v4 中的力导向网络图
【发布时间】:2018-01-23 12:52:53
【问题描述】:

我正在尝试在 d3v4 中添加矩形和圆形节点,尽管节点都被组合在一个角落并且它们的位置没有被更新,但该图仍然有效。我不知道我做错了什么?

我尝试在网上寻找示例,但似乎找不到任何专门使用 d3v4 的示例

<!DOCTYPE html>
<meta charset="UTF-8">
<style>

</style>
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>

// Properties
var width = 800;
var height = 600;
var nominal_stroke = 4;

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

// Create SVG window
var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);
var g = svg.append("g");
svg.style("cursor", "move");

// Load JSON data
d3.json("./network.json", function(error, graph) {
    console.log(graph);
    if (error) throw error;

    // Draw links
    var link = g.selectAll(".link")
        .data(graph.links)
        .enter().append("line")
        .attr("class", "link")
        .style("stroke-width", nominal_stroke)
        .style("stroke", "#999")
        .style("stroke-opacity", 0.6);

    // Draw nodes
    var node = g.selectAll(".node")
        .data(graph.nodes)
        .enter().append("g")
        .attr("class", "node")
        .call(d3.drag()
            .on("start", dragstarted)
            .on("drag", dragged)
            .on("end", dragended));

    // Setup node properties
    var circle = node.append("path")
        .attr("d", d3.symbol()
        .type(function (d) {
            if
            (d.shape == "rect") {
                return d3.symbolSquare;
            } else if
            (d.shape == "circle") {
                return d3.symbolCircle;
            }
        })
            .size(400))
    .style("stroke", "#999")
    .style("stroke-opacity", 0.6)
    .style("fill", function (d) {
        return "blue"
    });

// Add titles
    node.append("title")
        .text(function (d) {return d.id;});

    // Start Simulation
    simulation
        .nodes(graph.nodes)
        .on("tick", ticked);

    simulation.force("link")
        .links(graph.links);

    // Refresh page
    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("cx", function(d) { return d.x; })
            .attr("cy", function(d) { return d.y; });
    }

    // Zoom handler
    svg.call(d3.zoom()
        .scaleExtent([1 / 2, 8])
        .on("zoom", zoomed));

    function zoomed() {
        node.attr("transform", d3.event.transform);
        link.attr("transform", d3.event.transform);
    }

});


// Functions

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 = d.x;
    d.fy = d.y;
}

function openLink() {
    return function (d) {
        var url = "";
        if (d.url != "") {
            url = d.url
        }
        window.open(url)
    }
}


</script>
</body>

【问题讨论】:

    标签: javascript html d3.js svg


    【解决方案1】:

    您不应在ticked 函数中使用cxcy,因为您处理的是&lt;path&gt;s,而不是&lt;circle&gt;s。你应该改用translate

    因此,它必须是:

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

    这是您的更改代码(我在这里使用假数据):

    var width = 600;
    var height = 400;
    var nominal_stroke = 4;
    
    // Simulation
    var simulation = d3.forceSimulation()
      .force("link", d3.forceLink().id(function(d) {
        return d.id;
      }))
      .force("charge", d3.forceManyBody().strength(-400))
      .force("center", d3.forceCenter(width / 2, height / 2));
    
    // Create SVG window
    var svg = d3.select("body").append("svg")
      .attr("width", width)
      .attr("height", height);
    var g = svg.append("g");
    svg.style("cursor", "move");
    
    graph = {
      nodes: [{
        id: 1,
        shape: "rect"
      }, {
        id: 2,
        shape: "circle"
      }, {
        id: 3,
        shape: "rect"
      }, {
        id: 4,
        shape: "rect"
      }, {
        id: 5,
        shape: "circle"
      }, {
        id: 6,
        shape: "circle"
      }, {
        id: 7,
        shape: "circle"
      }],
      links: [{
        source: 1,
        target: 2
      }, {
        source: 1,
        target: 3
      }, {
        source: 1,
        target: 4
      }, {
        source: 1,
        target: 5
      }, {
        source: 3,
        target: 6
      }, {
        source: 3,
        target: 7
      }]
    }
    
    // Draw links
    var link = g.selectAll(".link")
      .data(graph.links)
      .enter().append("line")
      .attr("class", "link")
      .style("stroke-width", nominal_stroke)
      .style("stroke", "#999")
      .style("stroke-opacity", 0.6);
    
    // Draw nodes
    var node = g.selectAll(".node")
      .data(graph.nodes)
      .enter().append("g")
      .attr("class", "node")
      .call(d3.drag()
        .on("start", dragstarted)
        .on("drag", dragged)
        .on("end", dragended));
    
    // Setup node properties
    var circle = node.append("path")
      .attr("d", d3.symbol()
        .type(function(d) {
          if (d.shape == "rect") {
            return d3.symbolSquare;
          } else if (d.shape == "circle") {
            return d3.symbolCircle;
          }
        })
        .size(400))
      .style("stroke", "#999")
      .style("stroke-opacity", 0.6)
      .style("fill", function(d) {
        return "blue"
      });
    
    // Add titles
    node.append("title")
      .text(function(d) {
        return d.id;
      });
    
    // Start Simulation
    simulation
      .nodes(graph.nodes)
      .on("tick", ticked);
    
    simulation.force("link")
      .links(graph.links);
    
    // Refresh page
    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 + ")";
      });
    }
    
    // Zoom handler
    svg.call(d3.zoom()
      .scaleExtent([1 / 2, 8])
      .on("zoom", zoomed));
    
    function zoomed() {
      g.attr("transform", d3.event.transform);
    }
    
    
    // Functions
    
    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 = d.x;
      d.fy = d.y;
    }
    &lt;script src="https://d3js.org/d3.v4.min.js"&gt;&lt;/script&gt;

    PS:您的缩放功能不起作用,这是一个不同的问题。我也修好了。

    【讨论】:

    • 谢谢,这行得通,虽然在缩放或拖动节点时不会与线条保持一致,有没有办法让这个也起作用?
    • 正如我在 Post Scriptum 中所说,这是一个不同的问题。请发布一个关于此的新问题。
    • 您知道是否有解决此问题的方法吗?
    • 是的,当然有。再看看我的sn-p。
    猜你喜欢
    • 2015-08-12
    • 1970-01-01
    • 2018-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-04
    • 2019-03-30
    • 2013-12-05
    相关资源
    最近更新 更多