首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何动态更新此D3JS力图

如何动态更新此D3JS力图
EN

Stack Overflow用户
提问于 2020-09-11 16:20:01
回答 1查看 157关注 0票数 0

我已经从D3JS,https://observablehq.com/@d3/force-directed-graph改编了这个力有向图的例子。我使用VueJS从调用代码,所以我将其实现为一个类。

初始图形运行良好,但当我尝试添加新数据时,它没有响应。据我所知,如果我可以访问D3边和顶点选择,我应该能够在任何时候调用它们的join()函数,输入新数据,这应该会自动合并它。也许我弄错了?

下面的代码相当长,但只有两个值得注意的方法。首先,一旦D3Diagram对象被实例化,我就会使用边和顶点数组调用initialise()。稍后,当我想要添加更多数据时,我使用新的数组调用addMoreData()方法。

代码语言:javascript
复制
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);
}
EN

回答 1

Stack Overflow用户

发布于 2020-09-11 18:41:05

在D3中,数据被绑定到选择。您可以使用data()函数进行绑定。如果您想要更新您的选择,请使用现有的选择并再次绑定数据。这将创建一个新的选择,并且该新选择的enterupdateexit选择将包含更改的元素。

例如,更改数据:

代码语言:javascript
复制
// Initial, empty selection.
this.vertexSelection = this.svg.append("g")
    .attr("stroke", "#fff")
    .attr("stroke-width", 0.5)

// Bind the data once.
this.vertexSelection.data(data)

// Data join, creating new elements.
this.vertexSelection.join("line")

// Bind the data again.
this.vertexSelection.data(data)

// Data join. Will update, removing old data, appending new data, 
// updating existing data.
this.vertexSelection.join("line")

您将注意到,根据设计,数据更新时的调用总是相同的,除了初始化选择。所以我们可以把所有这些放在一个幂等的render()方法中:无论这是第一次调用,还是第二次、第三次调用,它都会工作。打电话。

然后,您可以像在当前代码中一样拆分它。您可以在组件挂载时调用init() & render()来执行第一次呈现,并在有新数据时调用render()

代码语言:javascript
复制
// pseudocode

function init() {
  // Initial, empty selection.
  this.vertexSelection = this.svg.append("g")
    .attr("stroke", "#fff")
    .attr("stroke-width", 0.5)
}

function render(data) {
  // Bind new data and do the data join.
  this.vertexSelection
    .data(this.data.vertexes)
    .join("line")
}

mounted() {
  this.init()
  this.render()
}

// on data change... {
  this.render()
// }

有关更深入的信息,请访问check out the selection.join() tutorial.

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63843351

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档