代码之家  ›  专栏  ›  技术社区  ›  VincentDM

D3v4插入新节点

  •  1
  • VincentDM  · 技术社区  · 8 年前

    编辑: added codepen example

    var svgRef = d3.select("body").append("svg")
        .attr("width",svgWidth)
        .attr("height",svgHeight)
        .on("mousedown",svgClick);
    
    var nodes_data = [{id: "0"},{id: "1"},{id: "2"}];
    var links_data = [{source:"1",target:"2"}];
    
    var linksRef = svgRef
        .selectAll(".link")         
        .data(links_data).enter()
        .append("line").attr("class", "link");
    
    var nodesRef = svgRef
        .append("g").attr("class", "nodes")
        .selectAll(".node")
        .data(nodes_data).enter()
        .append("g").attr("class", "node")
        .call(d3.drag()...);
    
    nodesRef.append("circle")
        .attr("r", nodeRadius);
    

    我正在为每个节点创建一个组来保存 circle title text 等等,所有这些节点都是在一个更大的“节点”组下创建的。最终结果如下:

    <svg>
        ...
        <g class="nodes">
            <g class="node">
                <circle>
                <text>
                ...
            </g>
            <g class="node"></g>
            <g class="node"></g>
            ...
        </g>
    </svg>
    

    尝试 在图表中插入

    function svgClick(){
    
        // add new node
        nodes_data.push({id: nodeCount++, "x":d3.event.X, "y":d3.event.y});
    
        // restart simulation
        simulation.nodes(nodes_data).on("tick", ticked);
    
        // insert new nodes
        nodeEnter = svgRef
            .selectAll(".node")
            .data(nodes_data).enter()
            .append("g").attr("class", "node")
            .call(d3.drag()...)
            .append("circle")
                .attr("class", "node")
                .attr("r", nodeRadius);
    
        // merge new nodes
        nodesRef = nodeEnter.merge(nodesRef);
    }
    

    • 插入的节点不会出现在鼠标坐标处 发现了这个,只是一个打字错误 d3.event.X 必须小写

    • 插入的节点未添加到 <g class="nodes"> 但在下面。我找不到合适的选择

    <svg>
        <g class="nodes">
            <g class="node"></g>
            <g class="node"></g>
        </g>
        <g class="node"></g>  // <--- inserted here
    </svg>
    
    1 回复  |  直到 8 年前
        1
  •  1
  •   Andrew Reid    8 年前

    对于您的第二个问题:“插入的节点未添加到,但在下面。“我找不到正确选择它的方法”,如何输入新节点解释了为什么最终会使用您拥有的结构:

    nodeEnter = svgRef
     .selectAll(".node")   // select all elements with class node in the svg
     .data(nodes_data)     // bind new data to them
      .enter()             // enter new nodes where needed
     .append("g")          // append a g for each new node needed to the svg
    

    svgRef.selectAll(...)... .

    如果要将新节点附加到父节点,则必须首先选择该父节点。如果我们想使用 g nodes 作为新节点的父元素,我们将使用: svgRef.select(".nodes").selectAll(...)... .

    nodeEnter = svgRef
      .select(".nodes")     // select the parent g with class nodes
      .seleactAll(".node")  // select all nodes in that parent
      .data(nodes_data)     // bind new data to them
      .enter()              // enter new nodes where needed
      .append("g")          // append a g for each new node needed to the g with class nodes
    

    元素,而不是 circle 元素,所以你可以在这里分开你的链子。圆也不需要类节点,因为父g拥有它

    对于定位,您使用 d3.event.X 而不是 d3.event.x

    这是一个 updated pen

    请记住,如果记号向下缠绕,则新节点的位置不会与放置在每个记号上的位置相同,而不是附加(如果要确保记号,请重置alpha)。另外,您可能看到的跳跃是由于d3.force center,它试图确保节点的重心是指定的点(如果要避免该问题,可以应用定位力而不是d3.forceCenter)