我创建了一个简单的D3 Force Layout图。 Please check it out in the JSFiddle here.
图表非常基础 - 它将城市作为节点连接到表示他们所在的节点的节点。为简单起见,我只制作了六个节点。
我创建了一个名为deleteNodeOnClick()
的函数,并将其设置在nodes
上,就像这样
var nodeEnter = node.enter()
.append('g')
.attr('class', 'node')
.on("click", deleteNodeOnClick)
当您点击图表中的某个节点时,该节点将从数据中删除(实际上为了简单起见,第一个节点暂时从数据中删除)但是它不会从可视图中删除。您可以查看控制台,看看它实际上是从数据中删除的。
为什么不呢?我完全被难过了。
var data = {
nodes: [{
name: "Canada"
}, {
name: "Montreal"
}, {
name: "Toronto"
}, {
name: "USA"
}, {
name: "New York"
}, {
name: "Los Angeles"
}],
links: [{
source: 0,
target: 1
}, {
source: 0,
target: 2
}, {
source: 3,
target: 4
}, {
source: 3,
target: 5
}, ]
};
var node;
var link;
var force;
var width = 400,
height = 400;
var svg = d3.select("body").append("svg")
.attr("width", window.innerWidth)
.attr("height", window.innerHeight);
force = d3.layout.force()
.size([width, length])
.nodes(data.nodes)
.links(data.links)
.gravity(.1)
.alpha(0.01)
.charge(-400)
.friction(0.5)
.linkDistance(100)
.on('tick', forceLayoutTick);
var link = svg.selectAll(".link")
.data(data.links);
var linkEnter = link.enter()
.append('line')
.attr('class', 'link');
link.exit().remove();
node = svg.selectAll('.node')
.data(data.nodes, function(d){
return d.name;
});
node.exit().remove();
var nodeEnter = node.enter()
.append('g')
.attr('class', 'node')
.on("click", deleteNodeOnClick)
//.attr('r', 8)
//.attr('cx', function(d, i){ return (i+1)*(width/4); })
//.attr('cy', function(d, i){ return height/2; })
.call(force.drag);
nodeEnter
.append("circle")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", 10)
.style("fill", "purple");
nodeEnter
.append("text")
.text(function(d) { return d.name })
.attr("class", "label")
.attr("dx", 0)
.attr("dy", ".35em");
force.start();
function forceLayoutTick(){
node.attr("transform", function(d) {
// Keep in bounding box
d.x = Math.max(10, Math.min(width - 10, d.x));
d.y = Math.max(10, Math.min(height - 10, d.y));
return "translate(" + d.x + "," + 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; });
};
function deleteNodeOnClick(d){
var dataBefore = JSON.parse(JSON.stringify(data.nodes));
// Just delete the first node, for demonstration purposes
data.nodes.splice(0, 1);
console.info("Node should be removed", dataBefore, data.nodes);
}
#graph {
width: 100%;
height: 100%;
}
#graph svg {
background-color: #CCC;
}
.link {
stroke-width: 2px;
stroke: black;
}
.node {
background-color: darkslategray;
stroke: #138;
width: 10px;
height: 10px;
stroke-width: 1.5px;
}
.node text {
pointer-events: none;
font: 10px sans-serif;
}
.label {
display: block;
}
答案 0 :(得分:3)
在D3中,更改数据不会自动更改SVG(或画布或HTML ...)元素。你必须“重新绘制”你的dataviz。
好消息是你(几乎)有所有的选择。因此,为了向您展示一般概念,我将所有渲染代码放在draw
函数中,该函数在点击时调用:
function deleteNodeOnClick(d){
data.nodes = data.nodes.filter(function(e){
return e.name !== d.name;
});
draw();
}
查看演示:
var data = {
nodes: [{
name: "Canada"
}, {
name: "Montreal"
}, {
name: "Toronto"
}, {
name: "USA"
}, {
name: "New York"
}, {
name: "Los Angeles"
}],
links: [{
source: 0,
target: 1
}, {
source: 0,
target: 2
}, {
source: 3,
target: 4
}, {
source: 3,
target: 5
}, ]
};
var node;
var link;
var force;
var width = 400,
height = 400;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
draw();
function draw() {
force = d3.layout.force()
.size([width, height])
.nodes(data.nodes)
.links(data.links)
.alpha(0.01)
.charge(-400)
.friction(0.5)
.linkDistance(100)
.on('tick', forceLayoutTick);
var link = svg.selectAll(".link")
.data(data.links);
var linkEnter = link.enter()
.append('line')
.attr('class', 'link');
link.exit().remove();
node = svg.selectAll('.node')
.data(data.nodes, function(d) {
return d.name;
});
node.exit().remove();
var nodeEnter = node.enter()
.append('g')
.attr('class', 'node')
.on("click", deleteNodeOnClick)
//.attr('r', 8)
//.attr('cx', function(d, i){ return (i+1)*(width/4); })
//.attr('cy', function(d, i){ return height/2; })
.call(force.drag);
nodeEnter
.append("circle")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", 10)
.style("fill", "purple");
nodeEnter
.append("text")
.text(function(d) {
return d.name
})
.attr("class", "label")
.attr("dx", 0)
.attr("dy", ".35em");
force.start();
function forceLayoutTick() {
node.attr("transform", function(d) {
// Keep in bounding box
d.x = Math.max(10, Math.min(width - 10, d.x));
d.y = Math.max(10, Math.min(height - 10, d.y));
return "translate(" + d.x + "," + 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;
});
};
};
function deleteNodeOnClick(d) {
data.nodes = data.nodes.filter(function(e) {
return e.name !== d.name;
});
draw();
}
#graph svg {
background-color: #CCC;
}
.link {
stroke-width: 2px;
stroke: black;
}
.node {
background-color: darkslategray;
stroke: #138;
width: 10px;
height: 10px;
stroke-width: 1.5px;
}
.node text {
pointer-events: none;
font: 10px sans-serif;
}
.label {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<body></body>
当然,正如我所说,这只是为了给你一般的想法:例如,点击不会删除链接。但现在你知道如何把它付诸实践。
答案 1 :(得分:0)
你的功能对图表没有任何作用:(只是数据)
function deleteNodeOnClick(d){
var dataBefore = JSON.parse(JSON.stringify(data.nodes));
// Just delete the first node, for demonstration purposes
data.nodes.splice(0, 1);
console.info("Node should be removed", dataBefore, data.nodes);
}
从图表中重新渲染或删除...
示例,只是删除(特定)“点”
function deleteNodeOnClick(d) {
var theElement = node.filter(function(da, i) {
if (i === d.index) {
console.log(da);
return true;
}
})
console.dir(theElement);
theElement.remove();
var dataBefore = JSON.parse(JSON.stringify(data.nodes));
// Just delete the first node, for demonstration purposes
data.nodes.splice(d.index, 1);
console.info("Node should be removed", dataBefore, data.nodes);
}
请注意,不要删除连接OTHER节点的“line”,我将把这项练习留给你做。
更紧凑的版本,没有所有日志记录等。
function deleteNodeOnClick(d) {
d3.select(node[0][d.index]).remove();
data.nodes.splice(d.index, 1);
}
(为访问本网站的其他人添加) 对于d3版本4,这将是
function deleteNodeOnClick(d) {
d3.select(node._groups[0][d.index]).remove();
data.nodes.splice(d.index, 1);
}