Javascript 附加组将d3 force布局中的所有内容都搞乱了

Javascript 附加组将d3 force布局中的所有内容都搞乱了,javascript,d3.js,d3-force-directed,Javascript,D3.js,D3 Force Directed,我有一个d3 force sim卡,如果我要按如下方式添加节点: node = node.data(nodes, function(d) { return d.id;}); node.exit().remove(); node = node.enter().append('circle') .attr("class", function(d) {return d.type;}) .attr("r", 25)

我有一个d3 force sim卡,如果我要按如下方式添加节点:

node = node.data(nodes, function(d) { return d.id;});
       node.exit().remove();
       node = node.enter().append('circle')
            .attr("class", function(d) {return d.type;})
            .attr("r", 25)
            .merge(node);
一切正常-圆圈添加到正确的位置,呈现的html如下所示:

<svg width="1280" height="960">
    <g transform="translate(640,480)">
        <g stroke="#000" stroke-width="1.5">
            <line x1="197.7877989370864" y1="16.96383936157134" x2="113.39655998594978" y2="176.9054238213185"></line>
            <line x1="-99.71642802229279" y1="182.82652731678513" x2="-206.38001140055673" y2="35.62690731557146"></line>
            <line x1="-111.21899770908817" y1="-104.07607869492837" x2="9.724648489851102" y2="-238.28831674029004"></line>
            <line x1="-111.21899770908817" y1="-104.07607869492837" x2="73.66744043019104" y2="-114.11648500001087"></line>
            <line x1="197.7877989370864" y1="16.96383936157134" x2="10.328317030872993" y2="37.5171491536661"></line>
            <line x1="-99.71642802229279" y1="182.82652731678513" x2="10.328317030872993" y2="37.5171491536661"></line>
            <line x1="-111.21899770908817" y1="-104.07607869492837" x2="10.328317030872993" y2="37.5171491536661"></line>
            <line x1="197.7877989370864" y1="16.96383936157134" x2="73.66744043019104" y2="-114.11648500001087"></line>
        </g>
        <g prop="nodes" stroke="#000" stroke-width="1.5">
            <circle fill="some_image.png" class="Net" r="25" cx="197.7877989370864" cy="16.96383936157134"></circle>
            <circle fill="some_image.png" class="Net" r="25" cx="-99.71642802229279" cy="182.82652731678513"></circle>
            <circle fill="some_image.png" class="Net" r="25" cx="-111.21899770908817" cy="-104.07607869492837"></circle>
            <circle fill="some_image.png" class="Inst" r="25" cx="113.39655998594978" cy="176.9054238213185"></circle>
            <circle fill="some_image.png" class="Inst" r="25" cx="-206.38001140055673" cy="35.62690731557146"></circle>
            <circle fill="some_image.png" class="Inst" r="25" cx="9.724648489851102" cy="-238.28831674029004"></circle>
            <circle fill="some_image.png" class="Inst" r="25" cx="73.66744043019104" cy="-114.11648500001087"></circle>
            <circle fill="some_image.png" class="Internet" r="25" cx="10.328317030872993" cy="37.5171491536661"></circle>
        </g>
    </g>
</svg>
虽然我的代码似乎得到正确的解释(我追加组,附加图像和标签给他们),组保持静态,他们仍然在中间的SIM之间的顶部。此外,坐标变换似乎会转到图像,而不是组,我认为这是打破sim卡的原因:

<svg width="1280" height="960">
    <g transform="translate(640,480)">
        <g stroke="#000" stroke-width="1.5">
            <line x1="197.77682810226557" y1="16.981901068622136" x2="113.3585440445384" y2="176.90457630748227"></line>
            <line x1="-99.99450481197604" y1="182.94091641902205" x2="-206.13047480355274" y2="35.36287517221039"></line>
            <line x1="-111.19343747422879" y1="-103.71666033252438" x2="9.543859895654657" y2="-238.10758089494877"></line>
            <line x1="-111.19343747422879" y1="-103.71666033252438" x2="73.69734375869983" y2="-114.13138675745854"></line>
            <line x1="197.77682810226557" y1="16.981901068622136" x2="10.344170477990337" y2="37.84621823186521"></line>
            <line x1="-99.99450481197604" y1="182.94091641902205" x2="10.344170477990337" y2="37.84621823186521"></line>
            <line x1="-111.19343747422879" y1="-103.71666033252438" x2="10.344170477990337" y2="37.84621823186521"></line>
            <line x1="197.77682810226557" y1="16.981901068622136" x2="73.69734375869983" y2="-114.13138675745854"></line>
        </g>
    <g prop="nodes" stroke="#000" stroke-width="1.5">
        <g class="node"><image xlink:href="some_image.png" x="0" y="0" height="72" width="72" style="z-index: 3;"></image></g>
        <g class="node"><image xlink:href="some_image.png" x="-7.373688780783198" y="6.754902942615239" height="72" width="72" style="z-index: 3;"></image></g>
        <g class="node"><image xlink:href="some_image.png" x="1.2363864559502138" y="-14.087985964343622" height="72" width="72" style="z-index: 3;"></image></g>
        <g class="node"><image xlink:href="some_image.png" x="10.538470205147267" y="13.745568221620495" height="72" width="72" style="z-index: 3;"></image></g>
        <g class="node"><image xlink:href="some_image.png" x="-19.694269706308575" y="-3.4836390075862327" height="72" width="72" style="z-index: 3;"></image></g>
        <g class="node"><image xlink:href="some_image.png" x="18.866941955758957" y="-12.001604111035421" height="72" width="72" style="z-index: 3;"></image></g>
        <g class="node"><image xlink:href="some_image.png" x="-6.358980820385529" y="23.65509169134563" height="72" width="72" style="z-index: 3;"></image></g>
        <g class="node"><image xlink:href="some_image.png" x="-12.194453649142762" y="-23.479678451778437" height="72" width="72" style="z-index: 3;"></image></g>
        </g>
    </g>
</svg>

我很肯定使用群组会把一切都搞砸,但我不知道如何正确使用它们

谢谢你的帮助

以下是片段形式的完整force布局:


解析测试器
变量节点=[
{id:0,标签:'branch1',名称:'branch1'},
{id:1,标签:'branch2',名称:'branch2'},
{id:2,标签:'branch3',名称:'branch3'},
{id:3,标签:'leaf1',名称:'leaf1'},
{id:4,标签:'leaf2',名称:'leaf2'},
{id:5,标签:'leaf3',名称:'leaf3'},
{id:6,标签:'center',名称:'center'},
{id:7,标签:'leaf23',名称:'leaf23'}
];
变量链接=[
{源:0,目标:3,距离:150,权重:1},
{来源:1,目标:4,距离:150,重量:1},
{来源:2,目标:5,距离:150,重量:1},
{来源:7,目标:0,距离:150,权重:1},
{来源:7,目标:1,距离:150,重量:1},
{来源:7,目标:2,距离:150,重量:1},
{来源:1,目标:6,距离:150,重量:1},
{来源:2,目标:6,距离:150,重量:1}
];
//D3材料
变量宽度=640,高度=480;
//将SVG添加到viz的主体中
var svg=d3。选择('body')。追加('svg'))
.attr('width',width)
.attr('高度'),高度;
var模拟=d3.forceSimulation(节点)
.力(“电荷”,d3.力人体().力(-1000))
.力(“链接”,d3.力链接(链接).距离(200))
.force(“x”,d3.forceX())
.force(“y”,d3.forceY())
.alphaTarget(1)
。在(勾选)上;
var g=svg.append(“g”).attr(“transform”、“translate”(“+width/2+”,“+height/2+”)),
link=g.append(“g”).attr(“笔划”,即“#000”).attr(“笔划宽度”,1.5)。选择All(“链接”),
node=g.append(“g”).attr(“笔划”,即“#000”).attr(“笔划宽度”,1.5)。选择All(“节点”);
重启();
函数重新启动(){
//将常规更新模式应用于节点。
node=node.data(节点,函数(d){return d.id;});
node.exit().remove();
node=node.enter()
.append('g')
.append('图像')
.attr('xlink:href','http://i.imgur.com/Rx4N3wh.png')
.attr('width',25)
.attr('height',25)
.attr('x',函数(d){return d.x;})
.attr('y',函数(d){返回d.y;})
.合并(节点);
node.enter().selectAll('g')。append('text'))
.attr('text-anchor','middle')
.attr('dy','.35em'))
.attr('y',-40)
.文本(功能(d){
返回d.标签
});
//将常规更新模式应用于链接。
link=link.data(links,函数(d){返回d.source.id+“-”+d.target.id;});
link.exit().remove();
link=link.enter().append(“line”).merge(link);
//更新并重新启动模拟。
模拟。节点(节点);
模拟。力(“链接”)。链接(链接);
simulation.alpha(1.restart();
}
//*/
函数勾选(){
attr(“cx”,函数(d){return d.x;})
.attr(“cy”,函数(d){返回d.y;});
attr(“x1”,函数(d){返回d.source.x;})
.attr(“y1”,函数(d){返回d.source.y;})
.attr(“x2”,函数(d){返回d.target.x;})
.attr(“y2”,函数(d){返回d.target.y;});
}
首先,我做了第二件事,链式方法之间有一个额外的}和几个逗号:

因此,从我的理解来看,在第一把小提琴中,一切都很好:链接和节点按照部队布局的指示移动。在fiddle two中,链接继续移动,但是现在带有图像的节点不会移动

根据我的理解,关键问题是“为什么
g
节点破坏了部队布局?”但似乎还有一些潜在问题,涉及每个
g
节点中的勾号函数和嵌套元素

强制勾选功能和更新模式

让我们看一下用于以下两种情况的勾号函数:

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; });
}
tick函数称为every tick,它根据其基准更新每个节点。力模拟不操纵视觉元素,而是操纵节点数据数组。初始化时,d3力为数据数组中的每个节点创建新属性,例如表示速度和位置的属性。所以d3是在更新你的数据,而不是你的元素。这就是为什么我们需要一个勾号函数

现在,上述不是d3中的典型更新模式(但对于d3部队来说,它是规范的)。典型的更新模式通常如下所示:

d3.selectAll(".node")
 .data(data)
 .attr("...")
 .attr("...")...
链可以通过中间的退出/进入/合并选择进行拆分

然而,对于对象,即数据数组中的节点,d3不会复制数据以将其绑定到每个元素,d3实际上会将每个元素链接到数据数组中的一个项。这意味着使用
node.attr(“cx”),函数(d){
d
指的是链接/绑定更新的
d3.selectAll(".node")
 .data(data)
 .attr("...")
 .attr("...")...
node = node.enter()      
   .append('g')      // returns a selection of `g` elements
   .append('image')  // returns a selection of `image` elements.
   ...
    node.attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; });  
node.attr("transform", function(d) { return "translate("+[d.x,d.y]+")"; })
      node.enter().selectAll('g').append('text')
        .attr('text-anchor', 'middle')
        .attr('dy', '.35em')
        .attr('y', -40)
        .text(function (d) {
            return d.label
        });
node.append("text")....