d3打字稿中的更新示例 - 范围问题?

时间:2018-03-07 14:28:28

标签: angular typescript d3.js

我无法使用this bl.ocks example在Typescript中工作(使用Angular)。

我在TypeScript中的尝试:StackBlitz

有没有人知道这里发生了什么?我猜这与变量在打字稿中的作用方式有关,因为我相信我正确地投了一切。如果您有任何建议,请告诉我。

Bl.ocks示例:

var svg = d3.select("svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height"),
    color = d3.scaleOrdinal(d3.schemeCategory10);

var a = {id: "a"},
    b = {id: "b"},
    c = {id: "c"},
    nodes = [a, b, c],
    links = [];

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

var g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + 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");

restart();

d3.timeout(function() {
  links.push({source: a, target: b}); // Add a-b.
  links.push({source: b, target: c}); // Add b-c.
  links.push({source: c, target: a}); // Add c-a.
  restart();
}, 1000);

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

d3.interval(function() {
  nodes.push(c); // Re-add c.
  links.push({source: b, target: c}); // Re-add b-c.
  links.push({source: c, target: a}); // Re-add c-a.
  restart();
}, 2000, d3.now() + 1000);

function restart() {

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

  // Apply the general update pattern to the links.
  link = link.data(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(nodes);
  simulation.force("link").links(links);
  simulation.alpha(1).restart();
}

function ticked() {
  node.attr("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return 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; });
}

我的尝试:

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;

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

  ngOnInit() {
    this.buildViz();
  }

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

    var a = { id: "a" },
      b = { id: "b" },
      c = { id: "c" },
      links = [];

    var nodes = [{ id: "a" }, { id: "b" }, { id: "c" }];

    var simulation = d3.forceSimulation<any>(nodes)
      .force("charge", d3.forceManyBody().strength(-1000))
      .force("link", d3.forceLink(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");

    restart();

    d3.timeout(function () {
      links.push({ source: a, target: b }); // Add a-b.
      links.push({ source: b, target: c }); // Add b-c.
      links.push({ source: c, target: a }); // Add c-a.
      restart();
    }, 2000);

    d3.interval(function () {
      nodes.pop(); // Remove c.
      links.pop(); // Remove c-a.
      links.pop(); // Remove b-c.
      restart();
    }, 4000, d3.now());

    d3.interval(function () {
      nodes.push(c); // Re-add c.
      links.push({ source: b, target: c }); // Re-add b-c.
      links.push({ source: c, target: a }); // Re-add c-a.
      restart();
    }, 2000, d3.now() + 1000);

    function restart() {

      // Apply the general update pattern to the nodes.
      node = node.data(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(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(nodes);
      simulation.force<any>("link").links(links);
      simulation.alpha(1).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; });
    }
  }

}

D3 Forced Layout Example

1 个答案:

答案 0 :(得分:1)

我对你的代码进行了一些调查,发现你犯了两个错误:

1)在下面的代码中,您要创建与abc对象失去联系的节点阵列

var a = { id: "a" },
  b = { id: "b" },
  c = { id: "c" },
  links = [];

var nodes = [{ id: "a" }, { id: "b" }, { id: "c" }];

您需要在数组中保留与原始对象相同的引用:

var nodes = [a, b, c];

2)你设置了两个错误的延迟:

d3.interval(function () {
  nodes.pop(); // Remove c.
  links.pop(); // Remove c-a.
  links.pop(); // Remove b-c.
  restart();
}, 4000, d3.now());
   ^^^^^
 should be 2000 as in original example

<强> Forked Stackblitz Example