[英]How to prevent node caching
我已经使用d3.js创建了一个动态的力导向网络地图。 映射最初会获取所有网络节点,并以将节点连接在一起的线条显示的网络接口正确显示它们。 这一切都很好。
当用户决定过滤属于特定项目的网络接口时,这就是我遇到的问题。 我重用了相同的d3.layout.force实例,并运行了最初创建地图的相同功能,但使用了新数据。 为了使事情简单,我对源代码进行了很多压缩,删除了与问题无关的所有内容。
var _this = {
graphLayout : d3.layout.force(),
node : null,
link : null,
selectedProject : null,
/*****************************************************
Initialize engine
*****************************************************/
render : function() {
// Creates the SVG container, sets up markers and gradients and whatnots
// unnecessary for me to include here I think.
// Start simulation
_this.update();
// Apply event handling and set up onTick
},
/*****************************************************
Perform a data update. This will read data from an
external url, and redraw all graphics.
*****************************************************/
update : function(project) {
if (project !== undefined) {
_this.selectedProject = project;
}
url = 'someService'+(!project ? '/GetNodes' : '/GetNodesByProjectId?projectId='+project.ProjectNumber);
d3.json(url, function(json) {
// Update nodes based on data
// Apply data to graph layout
_this.graphLayout
.nodes(json.nodes)
.links(json.links)
// Even more parameters which are unnecessary for this question
.start();
// Join lines config
_this.link = d3.select(" svg > .lineContainer").selectAll("g.link").data(_this.graphLayout.links());
var group = _this.link.enter().append("svg:g")
// More attributes and click event handling for the lines
.attr('id', function(d) { return d.InterfaceNumber; });
group.append("svg:line");
_this.link.exit().remove();
// Node rendering config
_this.node = d3.select(" svg > .nodeContainer").selectAll("g.node").data(_this.graphLayout.nodes());
group = _this.node.enter().append("svg:g")
// More attributes and click event handling for the nodes
.attr('id', function(d) { return d.Id; });
group.append("svg:path")
.attr("d", _this.nodeSVGPath)
.attr("fill", function(d) { return "url(#blackGradient)"; });
这是我遇到问题的地方:
// Add label to node
group.append('svg:text').attr('class', 'label').attr('transform', 'translate(25, 30)').text(function(d,i) { return d.Name; });
_this.node.exit().remove();
});
},
当第二次调用update时,放在.text上的函数(d,i)似乎没有运行。 这是在d3中缓存的内容,还是我缺少了某些内容?
这里的问题是节点(或行)包含正确的数据对象,但是节点上显示的文本不匹配,这使我相信d3js完全重用了svg对象,但与新更新的对象交换了数据 。
是的,您错过了这一重要事实。 enter()函数创建数据的子选择,而该子选择尚无元素。 您应该改用以下方法:
// Node rendering config
_this.node = d3.select(" svg > .nodeContainer").selectAll("g.node").data(_this.graphLayout.nodes());
group = _this.node.enter().append("svg:g")
// More attributes and click event handling for the nodes
.attr('id', function(d) { return d.Id; });
group.append("svg:path")
.attr("d", _this.nodeSVGPath)
.attr("fill", function(d) { return "url(#blackGradient)"; });
// Add label to node
group.append('svg:text').attr('class', 'label').attr('transform', 'translate(25, 30)');
// now set the text for all g.node > g > text elements, new or old
_this.node.select('g > text').text(function(d,i) { return d.Name; });
_this.node.exit().remove();
由于group是_this.node的enter()子选择,因此它永远不会包含在每次调用之前创建的元素。 最后,在设置文本的位置,使用_this.node而不是group选择所有新的或旧的文本节点。 有帮助吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.