无法在D3.JS和Angular Typescript中显示节点之间的链接

问题描述 投票:0回答:2

我正在使用基于Simple Angular CLI的项目和d3-ng2-service,我在其中创建了一个组件来尝试使用Force Layouts。在执行代码时,节点会显示,但它们之间的链接不会显示。

d3component.html

<p>
  test-d3-component works!
</p>

d3component.css

.links line {
  stroke: #999;
  stroke-opacity: 0.6;
}

.nodes circle {
  stroke: #fff;
  stroke-width: 1.5px;
}

d3component.component.ts

import { Component, OnInit, ElementRef} from '@angular/core';
import { D3Service, D3, Selection } from 'd3-ng2-service';

@Component({
  selector: 'app-test-d3-component',
  templateUrl: './test-d3-component.component.html',
  styleUrls: ['./test-d3-component.component.css']
})
export class TestD3ComponentComponent implements OnInit {
  private d3: D3;
  private parentNativeElement: any;
  svg;     // for dynamic svg addition to component
  link;    // link creation
  node;    // node creation
  simulation;  // force simulation
  color;  // color of nodes

  constructor(element: ElementRef, d3service: D3Service) {
    this.d3 =  d3service.getD3(); // get D3Service....
    this.parentNativeElement = element.nativeElement; // parent native component
  }

  ngOnInit() {
    // add the SVG graphic
    this.svg = this.d3.select(this.parentNativeElement).append('svg');
    // height, width, color selection
    this.svg.attr('width', 1000).attr('height', 800);
    this.color = this.d3.scaleOrdinal(this.d3.schemeCategory20);

    // Force Layout Simulation for D3
    this.simulation = this.d3.forceSimulation()
      .force("link", this.d3.forceLink().id(function(d: {id: string, group: number})
       { return d.id; }))
      .force('charge', this.d3.forceManyBody())
      .force('center', this.d3.forceCenter(1000/2, 800/2));
      // call the rendering function with a fix json for now..
      this.render({
        'nodes': [
        {'id': 'Alice', 'group': 1},
        {'id': 'Bob', 'group': 2},
        {'id': 'Cathy', 'group': 3}
      ],
      'links': [
        {'source': 'Alice', 'target': 'Bob', 'value': 1},
        {'source': 'Bob', 'target': 'Cathy', 'value': 2},
      ]
    });

  }

  ticked() {
    this.link
      .attr("x1", (d) => { return d.source.x; })
      .attr("y1", (d) => { return d.source.y; })
      .attr("x2", (d) => { return d.target.x; })
      .attr("y2", (d) => { return d.target.y; });

  this.node
      .attr("cx", (d) => { return d.x; })
      .attr("cy", (d) => { return d.y; });
  }


 /*
      Rendering Function
  */

  render(graph): void {
    this.link = this.svg.append('g')
        .attr('class', 'links')
        .selectAll('line') // from the CSS file
        .data(graph.links)
        .enter().append('line')
        .attr("stroke-width", (d) => { return Math.sqrt(d.value); });

    this.node = this.svg.append('g')
        .attr('class', 'nodes')
        .selectAll('circle') // from the CSS file
        .data(graph.nodes)
        .enter().append('circle')
        .attr('r', 10)
        .attr('fill', (d: any) => {
          return this.color(d.group);
        })
        .call(this.d3.drag()
          .on('start', (d) => {return this.dragStarted(d);})
          .on('drag', (d) => {return this.dragged(d);})
          .on('end', (d) => {return this.dragEnd(d);})
        );
        this.node.append('title')
          .text( (d) => { return d.id});
          this.simulation
      .nodes(graph.nodes)
      .on("tick", ()=>{return this.ticked()});

    this.simulation.force("link")
      .links(graph.links);
    }

  dragged(d): void {
    d.fx = this.d3.event.x;
    d.fy = this.d3.event.y;
  }

  dragEnd(d): void {
    if (!this.d3.event.active) this.simulation.alphaTarget(0);
    d.fx = null;
    d.fy = null;
  }

  dragStarted(d):void {
    if (!this.d3.event.active) this.simulation.alphaTarget(0.3).restart();
    d.fx = d.x;
    d.fy = d.y;
  }

  ngAfterViewInit() {}



}

输出渲染

enter image description here

我不知道为什么links没有在这里渲染,因为我在答案中基于这个代码类似于SE ThreadRelated Plunker

即使使用给定的miserables.json,渲染也提供节点而不是链接

miserables data

angular typescript d3.js
2个回答
1
投票

这可能会对其他人有所帮助。

我有同样的问题,并通过添加链接描边的颜色来修复它。尝试添加:

.attr("stroke", (d)=> { return "#D3D3D3"; });

紧接着:

.attr('stroke-width', (d) => Math.sqrt(d['value']))

0
投票

我发现了一个相当simple repository for the same graph on GitHub安装d3库并将其直接导入角度组件文件。我想在D3的v4.x中包含了打字。因此代码如下:

d3component.component.html

<p>
  test-d3-component works!
</p>

<svg width="800" height="1000"></svg>

d3component.component.ts

import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import * as d3 from 'd3';
import { miserables, test } from './miserables';
@Component({
  selector: 'app-test-d3-component',
  templateUrl: './test-d3-component.component.html',
  styleUrls: ['./test-d3-component.component.css'],
  encapsulation: ViewEncapsulation.None // this is new...
})

export class TestD3ComponentComponent implements OnInit {
 // kept the code same according to the Thread
  svg;
  width;
  height;
  color;
  simulation;
  link;
  node;

  ngOnInit() {
      console.log('D3.js version:', d3['version']);

      this.loadForceDirectedGraph();
    }
  // Rendering 

  loadForceDirectedGraph() {
      this.svg = d3.select('svg');
      this.width = +this.svg.attr('width');
      this.height = +this.svg.attr('height');
      this.color = d3.scaleOrdinal(d3.schemeCategory20);

      this.simulation = d3.forceSimulation()
        .force('link', d3.forceLink().id((d) => d['id']))
        .force('charge', d3.forceManyBody())
        .force('center', d3.forceCenter(this.width / 2, this.height / 2));

      this.render(test);
  }

  render(data): void {
      this.link = this.svg.append('g')
        .attr('class', 'links')
        .selectAll('line')
        .data(data['links'])
        .enter()
        .append('line')
        .attr('stroke-width', (d) => Math.sqrt(d['value']));

      this.node = this.svg.append('g')
            .attr('class', 'nodes')
            .selectAll('circle')
            .data(data['nodes'])
            .enter()
            .append('circle')
            .attr('r', 10)
            .attr('fill', (d) => this.color(d['group']))
            .call(d3.drag()
              .on('start', (d) => {return this.dragStarted(d);})
              .on('drag', (d) => {return this.dragged(d);})
              .on('end', (d) => {return this.dragEnded(d);})
            );
      this.node.append('title')
          .text( (d) => { return d.id});
      this.simulation
      .nodes(data.nodes)
      .on("tick", ()=>{return this.ticked()});

    this.simulation.force("link")
      .links(data.links);
  }
  ticked() {
      this.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; });

    this.node
      .attr('cx', function(d) { return d['x']; })
      .attr('cy', function(d) { return d['y']; });
  }

  dragStarted(d): void {
    if (!d3.event.active) { this.simulation.alphaTarget(0.3).restart(); }
    d.fx = d.x;
    d.fy = d.y;
  }

  dragged(d): void {
    d.fx = d3.event.x;
    d.fy = d3.event.y;
  }

  dragEnded(d): void {
    if (!d3.event.active) { this.simulation.alphaTarget(0); }
    d.fx = null;
    d.fy = null;
  }
}

miserables.ts

export let test = {
  'nodes': [
    {'id': 'Alice', 'group': 2},
    {'id': 'Bob', 'group': 3},
    {'id': 'Cathy', 'group': 4}
  ],
  'links': [
    {'source': 'Alice', 'target': 'Bob', 'value': 2},
    {'source': 'Bob', 'target': 'Cathy', 'value': 4},
    {'source': 'Cathy', 'target': 'Alice', 'value': 6},
  ]
}

产量

Output

Inference

我认为d3.js v4.x提供了Typescript支持,因此可以很容易地安装和使用

npm install --save d3

如果on正在使用angular-cli,则无需在整个项目中设置d3文件夹。

© www.soinside.com 2019 - 2024. All rights reserved.