点击

时间:2017-04-23 18:57:06

标签: d3.js

我想在点击节点时以新的节点和边缘更新有向图。 我从这个例子https://bl.ocks.org/mbostock/1095795开始 但目前我不知道如何处理奇怪定位的新边(和箭头)。 https://jsfiddle.net/alfredopacino/z1ppabL0/

    var svg = d3.select("svg"),
        width = +svg.attr("width"),
        height = +svg.attr("height"),
        color = d3.scaleOrdinal(d3.schemeCategory10);

    var a = {id: "1"},
        b = {id: "2"},
        c = {id: "3"},
        nodes = [a, b, c],
        links = [],
        NODE_CNT = nodes.length; //the nodes count so long

    links.push({source: a, target: b}); // Add a-b.
    links.push({source: b, target: c}); // Add b-c.
    links.push({source: c, target: a}); // Add c-a.

    var simulation = d3.forceSimulation(nodes)
        .force("charge", d3.forceManyBody().strength(-1000))
        .force("link", d3.forceLink(links).distance(200))
        .force("x", d3.forceX())
        .force("y", d3.forceY())
        .alphaTarget(1)
        .on("tick", ticked);

    var g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"),
        link = g.append("g").attr("stroke", "#000").attr("stroke-width", 1.5).selectAll(".link");
    // build the arrow.
    svg.append("svg:defs").selectAll("marker")
        .data(["end"])      // Different link/path types can be defined here
        .enter().append("svg:marker")    // This section adds in the arrows
        .attr("id", String)
        .attr("viewBox", "0 -5 10 10")
        .attr("refX", 15)
        .attr("refY", -1.5)
        .attr("markerWidth", 6)
        .attr("markerHeight", 6)
        .attr("orient", "auto")
        .append("svg:path")
        .attr("d", "M0,-5L10,0L0,5");

    var node = g.append("g").attr("stroke", "#fff").attr("stroke-width", 1.5).selectAll(".node");

    update();

    function update() {

        // Apply the general update pattern to the nodes.
        node = node.data(nodes, function (d) {
            return d.id;
        });
        node.exit().remove();
        node = node.enter().append("circle").attr("fill", function (d) {
            return color(d.id);
        }).attr("r", 8).merge(node);
        node.on("click", addNodeAndEdges);

        // Apply the general update pattern to the links.
        link = link.data(links, function (d) {
            return d.source.id + "-" + d.target.id;
        });
        link.exit().remove();
        link = link.enter().append("line").merge(link)
            .attr("marker-end", "url(#end)"); //-----------------arrow----------

        // Update and restart the simulation.
        simulation.nodes(nodes);
        simulation.force("link").links(links);
        simulation.alpha(1).restart();
    }

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

        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;
            });
    }
    function addNodeAndEdges(d) {
        //select(d) references the data, not the element. You need to select(this)
        console.log(this)
        NODE_CNT++;
        nodes.push({id: NODE_CNT});
        links.push({source: {id: NODE_CNT}, target: {id: NODE_CNT - 1}});
        links.push({source: {id: NODE_CNT - 2}, target: {id: NODE_CNT}});

        d3.select(this).attr('r', 20)
            .style("fill", "lightcoral")
            .style("stroke", "red");
        update();
    }

1 个答案:

答案 0 :(得分:1)

问题出在您的addNodeAndEdges功能中。当您向nodeslinks添加新元素时,您将创建新对象,而不是引用现有对象。例如,当您推送源{id: 1}的链接时,这与源a不同。当力模拟设置x的{​​{1}}和y属性时,新链接的源节点也不会更新。因此,您添加的新路径没有x和y坐标。

Here's a fiddle that fixes that,对a中的现有对象使用一致引用。