D3js 在 enter() 上强制重复节点
D3js force duplicate nodes on enter()
我在使用 d3js 时遇到一些问题,我无法弄清楚发生了什么。这个想法是从一些端点数据(第一个 img)中绘制初始图形,这很好。每个节点都是可点击的,点击 ajax 调用该节点并根据当时的一些标准 returned 数据 nodes.push(xx), links.push( xx) 恰好添加了新节点并调用了 restart() 以绘制新节点和链接。问题是主图正在做正确的事情(没有在屏幕截图上显示,因为我不得不在第一张图上放置假数据,即调用端点 /record/id/first 不会 return 数据)但是那里是一堆随机节点出现在右下角。
您还可以在下面的示例中看到,即使在单击 first/second/third 后数据没有更改,但在 restart() 传递了相同的数据后 node.enter() 出现了一些问题在...
JS FIDDLE: http://jsfiddle.net/5754j86e/
var w = 1200,
h = 1200;
var nodes = [];
var links = [];
var node;
var link;
var texts;
var ids = [];
var circleWidth = 10;
var initialIdentifier = "marcin";
nodes = initialBuildNodes(initialIdentifier, sparql);
links = initialBuildLinks(sparql);
//Add SVG
var svg = d3.select('#chart').append('svg')
.attr('width', w)
.attr('height', h);
var linkGroup = svg.append("svg:g").attr("id", "link-group");
var nodeGroup = svg.append("svg:g").attr("id", "node-group");
var textGroup = svg.append("svg:g").attr("id", "text-group");
//Add Force Layout
var force = d3.layout.force()
.size([w, h])
.gravity(.05)
.charge(-1040);
force.linkDistance(120);
restart();
function restart() {
force.links(links)
console.log("LINKS ARE: ", links)
link = linkGroup.selectAll(".link").data (links);
link.enter().append('line')
.attr("class", "link");
link.exit().remove();
force.nodes(nodes)
console.log("NODES ARE: ", nodes)
node = nodeGroup.selectAll(".node").data (nodes);
node.enter().append("svg:g")
.attr("class", "node")
.call(force.drag);
node.append('circle')
.attr('cx', function(d) { return d.x; })
.attr('cy', function(d) { return d.y; })
.attr('r', circleWidth )
.attr('fill', function(d, i) {
if (i>0) { return palette.pink }
else { return palette.blue }
})
.on("click", function(d) {
nodeClicked (d);
})
.on('mouseenter', function(d){
nodeMouseEnter(d)
})
.on('mouseout', function(d){
nodeMouseOut(d)
});
node.exit().remove();
var annotation = textGroup.selectAll(".annotation").data (nodes);
annotation.enter().append("svg:g")
.attr("class", "annotation")
.append("text")
.attr("x", function(d) { return d.radius + 4 })
.attr("y", ".31em")
.attr("class", "label")
.text(function(d) { return d.name; });
annotation.exit().remove();
force.start();
}
function nodeClicked (d) {
// AJAX CALL happens here and bunch of nodes.push({name: "new name"}) happen
}
force.on('tick', function(e) {
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, i) {
return 'translate('+ d.x +', '+ d.y +')';
})
svg.selectAll(".annotation").attr("transform", function(d) {
var labelx = d.x + 13;
return "translate(" + labelx + "," + d.y + ")";
})
});
好的,我知道了,基于文档 (https://github.com/mbostock/d3/wiki/Selections#enter):
var update_sel = svg.selectAll("circle").data(data)
update_sel.attr(/* operate on old elements only */)
update_sel.enter().append("circle").attr(/* operate on new elements only */)
update_sel.attr(/* operate on old and new elements */)
update_sel.exit().remove() /* complete the enter-update-exit pattern */
从我的代码中,您可以看到我执行了 enter(),然后我在单独的语句中再次在节点上添加了圆圈。
node = nodeGroup.selectAll(".node").data (nodes);
node.enter().append("svg:g")
.attr("class", "node")
.call(force.drag);
node.append('circle')
.attr('cx', function(d) { return d.x; })
.attr('cy', function(d) { return d.y; })
.attr('r', circleWidth )
.attr('fill', function(d, i) {
if (i>0) { return palette.pink }
else { return palette.blue }
});
添加圆应该在 enter() 的范围内,否则它会发生在 all 节点上,而不仅仅是 new 节点,因此它应该是:
node.enter().append("svg:g")
.attr("class", "node")
.call(force.drag)
.append('circle')
.attr('cx', function(d) { return d.x; })
.attr('cy', function(d) { return d.y; })
.attr('r', circleWidth )
.attr('fill', function(d, i) {
if (i>0) { return palette.pink }
else { return palette.blue }
});
我在使用 d3js 时遇到一些问题,我无法弄清楚发生了什么。这个想法是从一些端点数据(第一个 img)中绘制初始图形,这很好。每个节点都是可点击的,点击 ajax 调用该节点并根据当时的一些标准 returned 数据 nodes.push(xx), links.push( xx) 恰好添加了新节点并调用了 restart() 以绘制新节点和链接。问题是主图正在做正确的事情(没有在屏幕截图上显示,因为我不得不在第一张图上放置假数据,即调用端点 /record/id/first 不会 return 数据)但是那里是一堆随机节点出现在右下角。
您还可以在下面的示例中看到,即使在单击 first/second/third 后数据没有更改,但在 restart() 传递了相同的数据后 node.enter() 出现了一些问题在...
JS FIDDLE: http://jsfiddle.net/5754j86e/
var w = 1200,
h = 1200;
var nodes = [];
var links = [];
var node;
var link;
var texts;
var ids = [];
var circleWidth = 10;
var initialIdentifier = "marcin";
nodes = initialBuildNodes(initialIdentifier, sparql);
links = initialBuildLinks(sparql);
//Add SVG
var svg = d3.select('#chart').append('svg')
.attr('width', w)
.attr('height', h);
var linkGroup = svg.append("svg:g").attr("id", "link-group");
var nodeGroup = svg.append("svg:g").attr("id", "node-group");
var textGroup = svg.append("svg:g").attr("id", "text-group");
//Add Force Layout
var force = d3.layout.force()
.size([w, h])
.gravity(.05)
.charge(-1040);
force.linkDistance(120);
restart();
function restart() {
force.links(links)
console.log("LINKS ARE: ", links)
link = linkGroup.selectAll(".link").data (links);
link.enter().append('line')
.attr("class", "link");
link.exit().remove();
force.nodes(nodes)
console.log("NODES ARE: ", nodes)
node = nodeGroup.selectAll(".node").data (nodes);
node.enter().append("svg:g")
.attr("class", "node")
.call(force.drag);
node.append('circle')
.attr('cx', function(d) { return d.x; })
.attr('cy', function(d) { return d.y; })
.attr('r', circleWidth )
.attr('fill', function(d, i) {
if (i>0) { return palette.pink }
else { return palette.blue }
})
.on("click", function(d) {
nodeClicked (d);
})
.on('mouseenter', function(d){
nodeMouseEnter(d)
})
.on('mouseout', function(d){
nodeMouseOut(d)
});
node.exit().remove();
var annotation = textGroup.selectAll(".annotation").data (nodes);
annotation.enter().append("svg:g")
.attr("class", "annotation")
.append("text")
.attr("x", function(d) { return d.radius + 4 })
.attr("y", ".31em")
.attr("class", "label")
.text(function(d) { return d.name; });
annotation.exit().remove();
force.start();
}
function nodeClicked (d) {
// AJAX CALL happens here and bunch of nodes.push({name: "new name"}) happen
}
force.on('tick', function(e) {
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, i) {
return 'translate('+ d.x +', '+ d.y +')';
})
svg.selectAll(".annotation").attr("transform", function(d) {
var labelx = d.x + 13;
return "translate(" + labelx + "," + d.y + ")";
})
});
好的,我知道了,基于文档 (https://github.com/mbostock/d3/wiki/Selections#enter):
var update_sel = svg.selectAll("circle").data(data)
update_sel.attr(/* operate on old elements only */)
update_sel.enter().append("circle").attr(/* operate on new elements only */)
update_sel.attr(/* operate on old and new elements */)
update_sel.exit().remove() /* complete the enter-update-exit pattern */
从我的代码中,您可以看到我执行了 enter(),然后我在单独的语句中再次在节点上添加了圆圈。
node = nodeGroup.selectAll(".node").data (nodes);
node.enter().append("svg:g")
.attr("class", "node")
.call(force.drag);
node.append('circle')
.attr('cx', function(d) { return d.x; })
.attr('cy', function(d) { return d.y; })
.attr('r', circleWidth )
.attr('fill', function(d, i) {
if (i>0) { return palette.pink }
else { return palette.blue }
});
添加圆应该在 enter() 的范围内,否则它会发生在 all 节点上,而不仅仅是 new 节点,因此它应该是:
node.enter().append("svg:g")
.attr("class", "node")
.call(force.drag)
.append('circle')
.attr('cx', function(d) { return d.x; })
.attr('cy', function(d) { return d.y; })
.attr('r', circleWidth )
.attr('fill', function(d, i) {
if (i>0) { return palette.pink }
else { return palette.blue }
});