D3.js 如何动态更新此D3JS力图
我已经改编了来自D3JS的这个力定向图示例。我使用VueJS从调用代码,因此我将其作为一个类实现 最初的图表运行良好,但当我尝试添加新数据时,它没有响应。就我所见,如果我可以访问D3边和顶点选择,我应该能够随时调用它们的D3.js 如何动态更新此D3JS力图,d3.js,D3.js,我已经改编了来自D3JS的这个力定向图示例。我使用VueJS从调用代码,因此我将其作为一个类实现 最初的图表运行良好,但当我尝试添加新数据时,它没有响应。就我所见,如果我可以访问D3边和顶点选择,我应该能够随时调用它们的join()函数,输入新数据,并自动合并它。也许我弄错了 下面的代码相当长,但只有两种值得注意的方法。首先,一旦D3Diagram对象被实例化,我调用带有边和顶点数组的initialise()。稍后,当我想添加更多数据时,我使用新数组调用addMoreData()方法 impor
join()
函数,输入新数据,并自动合并它。也许我弄错了
下面的代码相当长,但只有两种值得注意的方法。首先,一旦D3Diagram对象被实例化,我调用带有边和顶点数组的initialise()
。稍后,当我想添加更多数据时,我使用新数组调用addMoreData()
方法
import * as d3 from "d3";
export default class D3Diagram {
initialise(vertices, edges) {
this.vertices = vertices;
this.edges = edges;
this.createSvg();
this.createSimulation();
this.createEdgeSelection();
this.createVertexSelection();
this.configureSimulation();
}
createSvg() {
this.svg = d3.select('#diagram-wrapper')
.append('svg')
.attr('viewBox', [0, 0, 100, 100])
.classed('flex-grow-1', true);
}
createSimulation() {
this.simulation = d3.forceSimulation(this.vertices)
.force("link", d3.forceLink(this.edges).id(d => d.id))
.force("charge", d3.forceManyBody().strength(d => -4))
.force("center", d3.forceCenter(50, 50));
}
createEdgeSelection() {
this.edgeSelection = this.svg.append("g")
.attr("stroke", "#999")
.attr("stroke-opacity", 0.6)
.selectAll("line")
.data(this.edges)
.join("line");
this.edgeSelection.append("title").text(d => d.id);
}
createVertexSelection() {
this.vertexSelection = this.svg.append("g")
.attr("stroke", "#fff")
.attr("stroke-width", 0.5)
.selectAll("circle")
.data(this.vertices)
.join("circle")
.attr("r", 2)
.attr("fill", color)
.call(drag(this.simulation));
}
configureSimulation() {
this.simulation.on('tick', () => {
this.edgeSelection
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
this.vertexSelection
.attr("cx", d => d.x)
.attr("cy", d => d.y);
});
}
addMoreData(vertices, edges) {
this.vertexSelection.join(vertices);
this.edgeSelection.join(edges);
}
}
function color() {
const scale = d3.scaleOrdinal(d3.schemeCategory10);
return d => scale(d.group);
}
function drag(simulation) {
function dragstarted(event) {
if (!event.active) simulation.alphaTarget(0.3).restart();
event.subject.fx = event.subject.x;
event.subject.fy = event.subject.y;
}
function dragged(event) {
event.subject.fx = event.x;
event.subject.fy = event.y;
}
function dragended(event) {
if (!event.active) simulation.alphaTarget(0);
event.subject.fx = null;
event.subject.fy = null;
}
return d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended);
}
在D3中,数据绑定到选择。您可以使用
data()
函数进行绑定。
如果要更新选择,请获取现有选择并再次绑定数据。这将创建一个新的选择,该新选择的输入
、更新
、和退出
选择将包含更改的元素
例如,更改数据:
//初始的空选择。
this.vertexSelection=this.svg.append(“g”)
.attr(“笔划”、“fff”)
.attr(“笔划宽度”,0.5)
//绑定数据一次。
此.vertexSelection.data(数据)
//数据连接,创建新元素。
此.vertexSelection.join(“行”)
//再次绑定数据。
此.vertexSelection.data(数据)
//数据连接。将更新、删除旧数据、追加新数据、,
//更新现有数据。
此.vertexSelection.join(“行”)
您会注意到,根据设计,数据更新时的调用总是相同的,只是为了初始化选择。因此,我们可以将所有这些放在一个幂等函数的render()
方法中:不管这是第一个调用还是第二个、第三个调用,依此类推。。打电话
之后,您可以像在当前代码中那样拆分它。您可以在组件装载时调用init()
&render()
,以执行第一次渲染,并在有新数据时调用render()
//伪代码
函数init(){
//初始,空选择。
this.vertexSelection=this.svg.append(“g”)
.attr(“笔划”、“fff”)
.attr(“笔划宽度”,0.5)
}
函数渲染(数据){
//绑定新数据并进行数据连接。
这是顶点选择
.data(此.data.vertex)
.加入(“行”)
}
安装的(){
this.init()
this.render()
}
//关于数据更改。。。{
this.render()
// }
要获得更深入的信息,谢谢Hugo,但我不明白模拟如何/在何处适用。