代码之家  ›  专栏  ›  技术社区  ›  Kyle Krzeski

Typescript中的d3更新示例-范围问题?

  •  0
  • Kyle Krzeski  · 技术社区  · 6 年前

    我很难得到 this bl.ocks example 使用打字脚本(带角度)。

    我在TypeScript中的尝试: StackBlitz

    有人知道这里发生了什么吗? 我猜这与typescript中变量的作用域有关,因为我认为我正确地铸造了所有内容。如果你有什么建议,请告诉我。

    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 回复  |  直到 6 年前
        1
  •  1
  •   yurzui    6 年前

    我对您的代码进行了一些研究,发现您犯了两个错误:

    1) 在下面的代码中,您正在创建与 a , b c 物体

    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