在d3v4中将多个形状的节点添加到强制定向网络图中

时间:2018-01-23 12:52:53

标签: javascript html d3.js svg

我正在尝试在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>

1 个答案:

答案 0 :(得分:1)

您不应在cx函数中使用cyticked,因为您正在处理<path>,而不是<circle>。您应该使用translate代替。

因此,必须是:

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

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

&#13;
&#13;
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;
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
&#13;
&#13;
&#13;

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