【问题标题】:Large Force Directed Graph Dataset in D3/AngularD3/Angular 中的大型力有向图数据集
【发布时间】:2021-04-13 02:11:47
【问题描述】:

我正在使用 D3 和 Angular,但我在使用来自 .csv 解析器的大型数据集时遇到了减速问题。 我能够加载数据并保存在我的本地存储中以供使用,但是一旦加载,图表就会完全减速到爬行。我在客户端使用 Angular。

我应该通过服务器加载这些数据以加快速度吗?或

如何过滤数据集以显示我的 D3 图表?

D3.component

    @Component({
  selector: 'app-graph',
  templateUrl: './graph.component.html',
  styleUrls: ['./graph.component.scss']
})
export class GraphComponent implements OnInit {

  constructor() { }

  ngOnInit() {
    const retrievedObject = localStorage.getItem('graph');
    const graph = JSON.parse(retrievedObject);
    this.loadForceDirectedGraph(graph.nodes, graph.links);

  }

  loadForceDirectedGraph(nodes: Node[], links: Link[]) {
    const svg = d3.select('svg');
    const width = +svg.attr('width');
    const height = +svg.attr('height');

    const color = d3.scaleOrdinal(d3.schemeBlues[9]);


    const simulation = d3.forceSimulation()
      .force('link', d3.forceLink().id((d: Node) => d.name))// the id of the node
      .force("charge", d3.forceManyBody().strength(-5).distanceMax(0.5 * Math.min(width, height)))
      .force('center', d3.forceCenter(width / 2, height / 2));

    console.log(nodes, links);

    const link = svg.append('g')
      .attr('class', 'links')
      .selectAll('line')
      .data(links)
      .enter()
      .append('line')
      .attr('stroke-width', d => Math.sqrt(d.index))
      .attr('stroke', 'black');

    const node = svg.append('g')
      .attr('class', 'nodes')
      .selectAll('circle')
      .data(nodes)
      .enter()
      .append('circle')
      .attr('r', 8)
      .attr("fill", function(d) { return color(d.company); })
      .call(d3.drag()
        .on('start', dragStarted)
        .on('drag', dragged)
        .on('end', dragEnded)
      );

     node.append('text')
            .text((d) => d.company)
            .attr('x', 6)
            .attr('y', 3);


    node.append('title').text((d) => d.name);

    simulation
      .nodes(nodes)
      .on('tick', ticked);

    simulation.force<d3.ForceLink<any, any>>('link')
      .links(links);

    function ticked() {
      node
        .attr('cx', d => d.x)
        .attr('cy', d => d.y);

      link
          .attr('x1', d => d.source.x)
          .attr('y1', d => d.source.y)
          .attr('x2', d => d.target.x)
          .attr('y2', d => d.target.y);
    }

    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;
    }
  }

【问题讨论】:

  • 您尝试渲染多少个节点和链接?
  • @MichaelRovinsky
  • 节点和链接是 csv 文件中的 8000> 行。我不确定我最初如何过滤这个。

标签: javascript angular d3.js graph


【解决方案1】:

在 SVG 下渲染超过 10K 的元素是很困难的。我想在渲染之前过滤节点和链接。首先,在 zoom() 处理程序中计算视口边界,然后按坐标过滤节点和链接(仅渲染边界内的节点和链接)

const nodeIsVisible = node => 
    (node.x + node.r > 0 && 
    node.x - node.r < width &&
    node.y + node.r > 0 && 
    node.y - node.r < height); 

这是一个example,由 50K 个随机生成的圆圈组成,按坐标过滤。希望能给个方向……

【讨论】:

  • hmm 这让我知道我应该做什么,但我的实现似乎更简单一些。我将如何使用上面的代码执行此操作?
  • @kjamp 如果您提供一个有效的 sn-p 或使用有限的数据集(约 10 个节点/链接),它会有所帮助,这样就可以看到整个代码。
  • codesandbox.io/s/fast-shadow-omdm3?file=/src/app/login/… 我无法让它运行,但这是我的完整代码
  • 您的示例不起作用(我得到 CompileError)
  • 是的,我知道我不确定codesandbox是否支持角度材料,但我想分享我的完整代码以供参考
猜你喜欢
  • 2014-02-27
  • 2016-03-28
  • 1970-01-01
  • 1970-01-01
  • 2018-04-09
  • 1970-01-01
  • 2018-04-20
  • 2014-02-16
  • 2017-11-25
相关资源
最近更新 更多