簡體   English   中英

D3可視化-更新ngOnChanges(Angular / TypeScript)

[英]D3 Visualization - Updating in ngOnChanges (Angular / TypeScript)

我正在Angular項目中使用此d3 bl.ocks示例 ,盡管我試圖更新數據onChanges而不是內部buildViz函數。 在下面的示例中,我通過在ngOnInit中設置一個間隔來對此進行嘲笑。

我收到一條錯誤消息,它找不到節點數據( ERROR TypeError: Cannot read property 'data' of undefined )。 我猜這是因為該函數在buildViz函數本身之外被調用,盡管傳入節點和鏈接似乎無法解決問題。 有什么想法嗎?

我的重啟功能中的這一行出現錯誤:

node = node.data(_this.nodes, function (d) { return d.id; });

工作代碼: StackBlitz

我的代碼:

import { Component, Input, OnInit, ElementRef } from '@angular/core';
import * as d3 from 'd3';

@Component({
  selector: 'd3-viz',
  templateUrl: './d3-viz.html'
})
export class D3Viz {

  private host;

  width: number = 750;
  height: number = 500;

  a = { id: "a" };
    b = { id: "b" };
    c = { id: "c" };

  links = [
    { source: this.a, target: this.b },
    { source: this.b, target: this.c },
    { source: this.c, target: this.a }
  ];

  nodes = [this.a, this.b, this.c];

  constructor(private element: ElementRef) {
    this.host = d3.select(this.element.nativeElement);
  }

  ngOnInit() {
    this.buildViz();

      d3.interval(() => {
        this.nodes.pop(); // Remove c.
        this.links.pop(); // Remove c-a.
        this.links.pop(); // Remove b-c.
        this.buildViz('update');
      }, 2000, d3.now());

      d3.interval(() => {
        this.nodes.push(this.c);
        this.links.push({ source: this.b, target: this.c });
        this.links.push({ source: this.c, target: this.a });
        this.buildViz('update');
      }, 2000, d3.now() + 1000);

  }

    buildViz(update?) {

      let svg = this.host.append('svg')
        .attr('width', this.width)
        .attr('height', this.height);
      let color = d3.scaleOrdinal(d3.schemeCategory10);


      if(!update){

      var simulation = d3.forceSimulation<any>(this.nodes)
        .force("charge", d3.forceManyBody().strength(-1000))
        .force("link", d3.forceLink(this.links).distance(200))
        .force("x", d3.forceX())
        .force("y", d3.forceY())
        .alphaTarget(1)
        .on("tick", ticked);

      var g = svg.append("g").attr("transform", "translate(" + this.width / 2 + "," + this.height / 2 + ")"),
        link = g.append("g").attr("stroke", "#000").attr("stroke-width", 1.5).selectAll(".link"),
        node = g.append("g").attr("stroke", "#fff").attr("stroke-width", 1.5).selectAll(".node");

    }



      var restart = () => {

        // Apply the general update pattern to the nodes.
        node = node.data(this.nodes, function (d: any) { return d.id; });
        node.exit().remove();
        node = node.enter().append("circle").attr("fill", function (d: any) { return color(d.id); }).attr("r", 8).merge(node);

        // Apply the general update pattern to the links.
        link = link.data(this.links, function (d) { return d.source.id + "-" + d.target.id; });
        link.exit().remove();
        link = link.enter().append("line").merge(link);

        // Update and restart the simulation.
        simulation.nodes(this.nodes);
        simulation.force<any>("link").links(this.links);
        simulation.alpha(1).restart();
      }
      restart();


      function ticked() {
        node.attr("cx", function (d: any) { return d.x; })
          .attr("cy", function (d: any) { return d.y; })

        link.attr("x1", function (d: any) { return d.source.x; })
          .attr("y1", function (d: any) { return d.source.y; })
          .attr("x2", function (d: any) { return d.target.x; })
          .attr("y2", function (d: any) { return d.target.y; });
      }
    }

}

ngOnChanges是生命周期掛鈎, 當輸入發生更改 (輸入為帶有@Input裝飾器的Angular輸入) 觸發。

我真的不知道您在那兒的目標,因此我無法為您提供解決方案,但至少我可以告訴您為什么它不起作用。

至於您的錯誤,您可以這樣寫:

  d3.interval(function () {
    this.nodes.pop(); // Remove c.
    this.links.pop(); // Remove c-a.
    this.links.pop(); // Remove b-c.
    this.buildViz(this.nodes, this.links, 'update');
  }, 2000, d3.now());

在函數中使用this關鍵字時,它引用函數,而不是組件。 要更正此問題,請改用此命令:

  d3.interval(() => {
    this.nodes.pop(); // Remove c.
    this.links.pop(); // Remove c-a.
    this.links.pop(); // Remove b-c.
    this.buildViz(this.nodes, this.links, 'update');
  }, 2000, d3.now());

這是粗箭頭符號,您應該查看Google以獲得更多信息。

對於其他函數,例如function restart(nodes, links) ,如果要將其上下文綁定到您的類,則應將其寫為restart = (nodes, links) => {...}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM