我正在使用基于简单角度CLI的项目和d3-ng2-service
,我已经创建了一个组件来尝试使用强制布局。在执行代码时,节点会显示,但它们之间的链接不会显示。
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() {}
}
我不确定为什么links
未在此处呈现,因为我的代码基于答案中的SE Thread和Related Plunker
即使使用给定的miserables.json
,渲染也会提供节点而不是链接
答案 0 :(得分:1)
这可能会对其他人有所帮助。
我遇到了同样的问题并通过在链接描边添加颜色来修复它。尝试添加:
.attr("stroke", (d)=> { return "#D3D3D3"; });
之后:
.attr('stroke-width', (d) => Math.sqrt(d['value']))
答案 1 :(得分:0)
我发现了一个相当simple repository for the same graph on GitHub的安装 d3 库并将其直接导入角度组件文件。我认为 v4.x D3 包含的内容。因此代码如下:
<强> 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},
]
}
<强>输出强>
我认为 d3.js v4.x 提供了Typescript支持,因此可以使用
轻松安装和使用npm install --save d3
如果正在使用angular-cli
,则无需在整个项目中设置d3
文件夹。