我刚刚开始使用Angularjs 2和d3-ng2-service,我正在尝试使用网络图表。
我用例子
https://bl.ocks.org/mbostock/2675ff61ea5e063ede2b5d63c08020c7
并将其转换为d3-ng2-service。
我收到以下错误
"属性链接不存在force()"
类型使用以下代码
simulation.force("link")
.links(links);
下面列出的完整代码
import { Component, ElementRef, NgZone, OnDestroy, OnInit } from '@angular/core';
import { links, nodes} from './networkData.component';
import {
D3Service,
D3,
Axis,
ScaleLinear,
ScaleOrdinal,
Selection,
Simulation,
Transition
} from 'd3-ng2-service';
@Component({
selector: 'network1',
template: '<svg width="100%" height="100%"></svg>',
styleUrls: ['./network.component.css']
})
export class Network1Component implements OnInit, OnDestroy {
private d3: D3;
private parentNativeElement: any;
private d3Svg: Selection<SVGSVGElement, any, null, undefined>;
constructor(element: ElementRef, private ngZone: NgZone, d3Service: D3Service) {
this.d3 = d3Service.getD3();
this.parentNativeElement = element.nativeElement;
}
ngOnDestroy() {
if (this.d3Svg.empty && !this.d3Svg.empty()) {
this.d3Svg.selectAll('*').remove();
}
}
ngOnInit() {
let self = this;
let d3 = this.d3;
let width: number;
let height: number;
let d3ParentElement: Selection<HTMLElement, any, null, undefined>;
let d3Svg: Selection<SVGSVGElement, any, null, undefined>;
if (this.parentNativeElement !== null) {
d3ParentElement = d3.select(this.parentNativeElement);
d3Svg = this.d3Svg = d3ParentElement.select<SVGSVGElement>('svg');
width = +d3Svg.attr('width');
height = +d3Svg.attr('height');
var color = d3.scaleOrdinal(d3.schemeCategory20);
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) { return d[0].id; }))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2));
var link = d3Svg.append<SVGGElement>('g')
.attr("class", "links")
.selectAll("line")
.data(links)
.enter().append("line")
.attr("stroke-width", function(d) { return Math.sqrt(d.value); });
var node = d3Svg.append<SVGGElement>('g')
.attr("class", "nodes")
.selectAll("circle")
.data(nodes)
.enter().append("circle")
.attr("r", 5)
.attr("fill", function(d) { return color(d.id); });
node.append("title")
.text(function(d) { return d.id; });
simulation
.nodes(nodes)
.on("tick", ticked);
simulation.force("link")
.links(links);
}
function ticked() {
link
.attr("x1", function(d) { return d.source; })
.attr("y1", function(d) { return d.source; })
.attr("x2", function(d) { return d.target; })
.attr("y2", function(d) { return d.target; });
node
.attr("cx", function(d) { return d.id; })
.attr("cy", function(d) { return d.id; });
}
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
}
}
答案 0 :(得分:5)
在将bl.ock移植到TypeScript时,需要进行一些调整以确保节点和链接的数据类型以及正确处理不同的力类型。
forceSimulation
在调用时接受两个泛型。我们假设,您的节点类型为YourNodeType
,它扩展了SimulationNodeDatum
,链接类型为YourLinkType
,扩展了SimulationLinkDatum<YourNodeType>
。SimulationNodeDatum
和{{1}是 d3-force 定义中定义的接口。
话虽如此,你应该定义SimulationLinkDatum
这样,节点和你的情况重要的是链接类型在整个模拟过程中被强制执行。
现在,对于您遇到的错误的核心,为了检索具有除最小let simulation = d3.forceSimulation<YourNodeType, YourLinkType>()
接口之外的属性的力,必须将力强制转换为事前已知类型。在您的情况下,链接力在定义中具有预定义的接口。
所以Force
会返回一个定义为simulation.force<ForceLink<YourNodeType, YourLinkType>>('link')
方法的链接力。
由于您使用的是 d3-ng2-service ,因此可以直接从以下位置导入接口links()
,SimulationNodeDatum
和SimulationLinkDatum
。 ForceLink
放入包含角度组件的文件中。
如果您使用d3-ng2-service
,则可能需要strictNullChecks
,其中simulation.force<ForceLink<YourNodeType, YourLinkType>>('link')!.links()
解决返回的力量通常为!
的情况。事实并非如此。
希望这有帮助。
答案 1 :(得分:1)
汤姆的回答指出了我正确的方向,我设法让这个工作 - 谢谢汤姆。对于其他任何工作的人,在我的情况下,我还必须将.links(links)
添加到simulation.force()
,所以:
simulation.force("link").links(links);
变为:
simulation.force<ForceLink<any, any>>('link').links(links);
我会将此添加为评论,但我的代表不够高。