d3js 强制删除不使用 exit().remove() 的旧链接
d3js force-directed removal of old links not working with exit().remove()
当我修改布局时,我无法在使用 d3js 的力导向可视化中删除旧的 links。这意味着旧的 link 不会被删除,而是保留在标签中。我确实关注 this example 并做了以下事情:
link = link.data(links, function(d) {
return d.source.id + '-' + d.target.id;
});
link.enter().append("g").attr("class", "link");
var linkline = link.append("line").attr("class", "linkline");
var linktext = link.append("text").attr("class", "linktext")
.text(function(d) {
return d[setup.label_edge];
});
link.exit().remove();
其余与示例中的几乎相同。但是,我无法摆脱旧的 links,exit().remove() 将不起作用。他们将停留在可视化上。
这是我从 gilsha 执行 then 代码片段时得到的结果。 <g class="link">
标签中的 link 行和 link 文本仍然有多个条目。它们不可见并出现在左上角,但我仍然需要摆脱它们。因为当我拖动图形时,这就成了一个问题。
在新变量中写入link.append时,它不再复制行和标签,但在调用更新时,行留在以前的位置,不再移动。
这是打勾。我需要 link link 以某种方式分组吗?
force.on("tick", function(e){
linkline
.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;
});
linktext
.attr("x", function(d) {
return ((d.source.x + d.target.x)/2);
})
.attr("y", function(d) {
return ((d.source.y + d.target.y)/2);
});
node.attr("transform", function(d) {
if(setup.source == 0) {
if(d.id==0){
damper = 0.1;
d.x = d.x + ($('svg').attr('width')/2 - d.x) * (damper + 0.02) * e.alpha;
d.y = d.y + ($('svg').attr('height')/2 - d.y) * (damper + 0.02) * e.alpha;
}
var x = Math.max(radius, Math.min($('svg').attr('width') - radius, d.x));
var y = Math.max(radius, Math.min($('svg').attr('height') - radius, d.y));
return "translate(" + x + "," + y + ")";
} else {
if(d.id==0){
damper = 0.1;
d.x = d.x + ($('svg').attr('width')/2 - d.x) * (damper + 0.02) * e.alpha;
d.y = d.y + ($('svg').attr('height')/2 - d.y) * (damper + 0.02) * e.alpha;
}
var x = Math.max(radius, Math.min($('svg').attr('width') - imagesize2(d.metadata[setup.external[1]])[0], d.x));
var y = Math.max(radius, Math.min($('svg').attr('height') - imagesize2(d.metadata[setup.external[1]])[1], d.y));
return "translate(" + x + "," + y + ")";
}
});
问题中你添加的部分代码没有错误。问题将是由于代码的其他部分引起的。验证更新前后的数据集是否符合预期。
编辑:要解决 link 和文本的重复问题,请将 link 和 link 标签附加到 linkGroup
而不是 link
。由于您正在为 links 使用组元素,因此 links 的动态更新可能会导致 links 的分层问题(链接可能会覆盖节点)。您可以使用代码和代码段中所示的 insert
函数解决该问题。
link = link.data(links, function(d) {
return d.source.id + '-' + d.target.id;
});
/* var linkGroup = link.enter().insert("g",".node").attr("class", "link");//Use insert to resolve dom element layering issue. */
var linkGroup = link.enter().append("g").attr("class", "link");
var linkline = linkGroup.append("line")
.attr("class", "linkline");
var linktext = linkGroup.append("text")
.attr("class", "linktext")
.text(function(d, i) {
return i;
});
link.exit().remove();
var width = 960,
height = 500;
var color = d3.scale.category10();
var nodes = [],
links = [];
var force = d3.layout.force()
.nodes(nodes)
.links(links)
.charge(-400)
.linkDistance(120)
.size([width, height])
.on("tick", tick);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var node = svg.selectAll(".node"),
link = svg.selectAll(".link");
// 1. Add three nodes and three links.
setTimeout(function() {
var a = {
id: "a"
},
b = {
id: "b"
},
c = {
id: "c"
};
nodes.push(a, b, c);
links.push({
source: a,
target: b
}, {
source: a,
target: c
}, {
source: b,
target: c
});
start();
}, 0);
// 2. Remove node B and associated links.
setTimeout(function() {
nodes.splice(1, 1); // remove b
links.shift(); // remove a-b
links.pop(); // remove b-c
start();
}, 3000);
// Add node B back.
setTimeout(function() {
var a = nodes[0],
b = {
id: "b"
},
c = nodes[1];
nodes.push(b);
links.push({
source: a,
target: b
}, {
source: b,
target: c
});
start();
}, 6000);
function start() {
link = link.data(links, function(d) {
return d.source.id + '-' + d.target.id;
});
var linkGroup = link.enter().insert("g",".node").attr("class", "link"); //Use insert to resolve dom element layering issue.
//var linkGroup = link.enter().append("g").attr("class", "link");
var linkline = linkGroup.append("line")
.attr("class", "linkline");
var linktext = linkGroup.append("text")
.attr("class", "linktext")
.text(function(d, i) {
return i;
});
link.exit().remove();
node = node.data(force.nodes(), function(d) {
return d.id;
});
node.enter().append("circle").attr("class", function(d) {
return "node " + d.id;
}).attr("r", 8);
node.exit().remove();
force.start();
}
function tick() {
node.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
link.selectAll("line").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;
});
}
.link {
stroke: #000;
stroke-width: 1.5px;
}
.node {
fill: #000;
stroke: #fff;
stroke-width: 1.5px;
}
.node.a {
fill: #1f77b4;
}
.node.b {
fill: #ff7f0e;
}
.node.c {
fill: #2ca02c;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
当我修改布局时,我无法在使用 d3js 的力导向可视化中删除旧的 links。这意味着旧的 link 不会被删除,而是保留在标签中。我确实关注 this example 并做了以下事情:
link = link.data(links, function(d) {
return d.source.id + '-' + d.target.id;
});
link.enter().append("g").attr("class", "link");
var linkline = link.append("line").attr("class", "linkline");
var linktext = link.append("text").attr("class", "linktext")
.text(function(d) {
return d[setup.label_edge];
});
link.exit().remove();
其余与示例中的几乎相同。但是,我无法摆脱旧的 links,exit().remove() 将不起作用。他们将停留在可视化上。
这是我从 gilsha 执行 then 代码片段时得到的结果。 <g class="link">
标签中的 link 行和 link 文本仍然有多个条目。它们不可见并出现在左上角,但我仍然需要摆脱它们。因为当我拖动图形时,这就成了一个问题。
在新变量中写入link.append时,它不再复制行和标签,但在调用更新时,行留在以前的位置,不再移动。
这是打勾。我需要 link link 以某种方式分组吗?
force.on("tick", function(e){
linkline
.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;
});
linktext
.attr("x", function(d) {
return ((d.source.x + d.target.x)/2);
})
.attr("y", function(d) {
return ((d.source.y + d.target.y)/2);
});
node.attr("transform", function(d) {
if(setup.source == 0) {
if(d.id==0){
damper = 0.1;
d.x = d.x + ($('svg').attr('width')/2 - d.x) * (damper + 0.02) * e.alpha;
d.y = d.y + ($('svg').attr('height')/2 - d.y) * (damper + 0.02) * e.alpha;
}
var x = Math.max(radius, Math.min($('svg').attr('width') - radius, d.x));
var y = Math.max(radius, Math.min($('svg').attr('height') - radius, d.y));
return "translate(" + x + "," + y + ")";
} else {
if(d.id==0){
damper = 0.1;
d.x = d.x + ($('svg').attr('width')/2 - d.x) * (damper + 0.02) * e.alpha;
d.y = d.y + ($('svg').attr('height')/2 - d.y) * (damper + 0.02) * e.alpha;
}
var x = Math.max(radius, Math.min($('svg').attr('width') - imagesize2(d.metadata[setup.external[1]])[0], d.x));
var y = Math.max(radius, Math.min($('svg').attr('height') - imagesize2(d.metadata[setup.external[1]])[1], d.y));
return "translate(" + x + "," + y + ")";
}
});
问题中你添加的部分代码没有错误。问题将是由于代码的其他部分引起的。验证更新前后的数据集是否符合预期。
编辑:要解决 link 和文本的重复问题,请将 link 和 link 标签附加到 linkGroup
而不是 link
。由于您正在为 links 使用组元素,因此 links 的动态更新可能会导致 links 的分层问题(链接可能会覆盖节点)。您可以使用代码和代码段中所示的 insert
函数解决该问题。
link = link.data(links, function(d) {
return d.source.id + '-' + d.target.id;
});
/* var linkGroup = link.enter().insert("g",".node").attr("class", "link");//Use insert to resolve dom element layering issue. */
var linkGroup = link.enter().append("g").attr("class", "link");
var linkline = linkGroup.append("line")
.attr("class", "linkline");
var linktext = linkGroup.append("text")
.attr("class", "linktext")
.text(function(d, i) {
return i;
});
link.exit().remove();
var width = 960,
height = 500;
var color = d3.scale.category10();
var nodes = [],
links = [];
var force = d3.layout.force()
.nodes(nodes)
.links(links)
.charge(-400)
.linkDistance(120)
.size([width, height])
.on("tick", tick);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var node = svg.selectAll(".node"),
link = svg.selectAll(".link");
// 1. Add three nodes and three links.
setTimeout(function() {
var a = {
id: "a"
},
b = {
id: "b"
},
c = {
id: "c"
};
nodes.push(a, b, c);
links.push({
source: a,
target: b
}, {
source: a,
target: c
}, {
source: b,
target: c
});
start();
}, 0);
// 2. Remove node B and associated links.
setTimeout(function() {
nodes.splice(1, 1); // remove b
links.shift(); // remove a-b
links.pop(); // remove b-c
start();
}, 3000);
// Add node B back.
setTimeout(function() {
var a = nodes[0],
b = {
id: "b"
},
c = nodes[1];
nodes.push(b);
links.push({
source: a,
target: b
}, {
source: b,
target: c
});
start();
}, 6000);
function start() {
link = link.data(links, function(d) {
return d.source.id + '-' + d.target.id;
});
var linkGroup = link.enter().insert("g",".node").attr("class", "link"); //Use insert to resolve dom element layering issue.
//var linkGroup = link.enter().append("g").attr("class", "link");
var linkline = linkGroup.append("line")
.attr("class", "linkline");
var linktext = linkGroup.append("text")
.attr("class", "linktext")
.text(function(d, i) {
return i;
});
link.exit().remove();
node = node.data(force.nodes(), function(d) {
return d.id;
});
node.enter().append("circle").attr("class", function(d) {
return "node " + d.id;
}).attr("r", 8);
node.exit().remove();
force.start();
}
function tick() {
node.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
link.selectAll("line").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;
});
}
.link {
stroke: #000;
stroke-width: 1.5px;
}
.node {
fill: #000;
stroke: #fff;
stroke-width: 1.5px;
}
.node.a {
fill: #1f77b4;
}
.node.b {
fill: #ff7f0e;
}
.node.c {
fill: #2ca02c;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>