我正在尝试使用Angular 5上的D3-NG2服务服务来重现此示例。
组件:
ngoninit代码:
let d3 = this.d3;
let d3ParentElement: Selection<HTMLElement, any, null, undefined>;
let d3Svg: Selection<SVGSVGElement, any, null, undefined>;
let d3G: Selection<SVGGElement, any, null, undefined>;
let width: number;
let height: number;
if (this.parentNativeElement !== null) {
d3ParentElement = d3.select(this.parentNativeElement);
d3Svg = this.d3Svg = d3ParentElement.select<SVGSVGElement>('svg');
width = +d3Svg.attr('width');
height = +d3Svg.attr('height');
d3G = d3Svg.append<SVGGElement>("g")
.attr("transform", "translate(" + (width / 2 + 40) + "," + (height / 2 + 90) + ")");
let stratify = d3.stratify()
.parentId(function (d) {
return d["id"].substring(0, d["id"].lastIndexOf("."));
});
let tree = d3.tree()
.size([2 * Math.PI, 500])
.separation(function (a, b) {
return (a["parent"] == b["parent"] ? 1 : 2) / a["depth"];
});
//let data = this.gruppi;
let data = [
{id: "flare"},
{id: "flare.analytics"},
{id: "flare.analytics.cluster"},
{id: "flare.analytics.cluster.AgglomerativeCluster"},
{id: "flare.analytics.cluster.CommunityStructure"},
{id: "flare.analytics.cluster.HierarchicalCluster"},
{id: "flare.analytics.cluster.MergeEdge"},
{id: "flare.analytics.graph"},
{id: "flare.analytics.graph.BetweennessCentrality"},
{id: "flare.analytics.graph.LinkDistance"},
{id: "flare.analytics.graph.MaxFlowMinCut"},
{id: "flare.analytics.graph.ShortestPaths"},
{id: "flare.analytics.graph.SpanningTree"},
{id: "flare.analytics.optimization"},
{id: "flare.analytics.optimization.AspectRatioBanker"},
{id: "flare.animate"},
{id: "flare.animate.Easing"},
{id: "flare.animate.FunctionSequence"},
{id: "flare.animate.interpolate"},
{id: "flare.animate.interpolate.ArrayInterpolator"},
{id: "flare.animate.interpolate.ColorInterpolator"},
{id: "flare.animate.interpolate.DateInterpolator"},
{id: "flare.animate.interpolate.Interpolator"},
{id: "flare.animate.interpolate.MatrixInterpolator"},
{id: "flare.animate.interpolate.NumberInterpolator"},
{id: "flare.animate.interpolate.ObjectInterpolator"},
{id: "flare.animate.interpolate.PointInterpolator"},
{id: "flare.animate.interpolate.RectangleInterpolator"},
{id: "flare.animate.ISchedulable"},
{id: "flare.animate.Parallel"},
{id: "flare.animate.Pause"},
{id: "flare.animate.Scheduler"},
{id: "flare.animate.Sequence"},
{id: "flare.animate.Transition"},
{id: "flare.animate.Transitioner"},
{id: "flare.animate.TransitionEvent"},
{id: "flare.animate.Tween"},
{id: "flare.data"},
{id: "flare.data.converters"},
{id: "flare.data.converters.Converters"},
{id: "flare.data.converters.DelimitedTextConverter"},
{id: "flare.data.converters.GraphMLConverter"},
{id: "flare.data.converters.IDataConverter"},
{id: "flare.data.converters.JSONConverter"},
{id: "flare.data.DataField"},
{id: "flare.data.DataSchema"},
{id: "flare.data.DataSet"},
{id: "flare.data.DataSource"},
{id: "flare.data.DataTable"},
{id: "flare.data.DataUtil"},
{id: "flare.display"},
{id: "flare.display.DirtySprite"},
{id: "flare.display.LineSprite"},
{id: "flare.display.RectSprite"},
{id: "flare.display.TextSprite"},
{id: "flare.flex"},
{id: "flare.flex.FlareVis"},
{id: "flare.physics"},
{id: "flare.physics.DragForce"},
{id: "flare.physics.GravityForce"},
{id: "flare.physics.IForce"},
{id: "flare.physics.NBodyForce"},
{id: "flare.physics.Particle"},
{id: "flare.physics.Simulation"},
{id: "flare.physics.Spring"},
{id: "flare.physics.SpringForce"},
{id: "flare.query"},
{id: "flare.query.AggregateExpression"},
{id: "flare.query.And"},
{id: "flare.query.Arithmetic"},
{id: "flare.query.Average"},
{id: "flare.query.BinaryExpression"},
{id: "flare.query.Comparison"},
{id: "flare.query.CompositeExpression"},
{id: "flare.query.Count"},
{id: "flare.query.DateUtil"},
{id: "flare.query.Distinct"},
{id: "flare.query.Expression"},
{id: "flare.query.ExpressionIterator"},
{id: "flare.query.Fn"},
{id: "flare.query.If"},
{id: "flare.query.IsA"}
];
let root = tree(stratify(data));
let radial = d3.linkRadial()
.angle(function(d){ return d["x"];})
.radius(function(d){ return d["y"];});
let link = d3G.selectAll<SVGElement, any>(".link")
.data(root.links())
.enter()
.append<SVGPathSeg>("path")
.attr("class", "link")
.attr("d",radial);
let radialPoint = function(x, y) {
return [(y = +y) * Math.cos(x -= Math.PI / 2), y * Math.sin(x)];
};
let node = d3G.selectAll<SVGElement, any>(".node")
.data(root.descendants())
.enter()
.append<SVGGElement>("g")
.attr("class", function (d) {
return "node" + (d["children"] ? " node--internal" : " node--leaf");
})
.attr("transform", function (d) {
return "translate(" + radialPoint(d["x"], d["y"]) + ")";
});
node.append<SVGCircleElement>("circle")
.attr("r", 2.5);
node.append<SVGTextElement>("text")
.attr("dy", "0.31em")
.attr("x", function (d) {
return d["x"] < Math.PI === !d["children"] ? 6 : -6;
})
.attr("text-anchor", function (d) {
return d["x"] < Math.PI === !d["children"] ? "start" : "end";
})
.attr("transform", function (d) {
return "rotate(" + (d["x"] < Math.PI ? d["x"] - Math.PI / 2 : d["x"] + Math.PI / 2) * 180 / Math.PI + ")";
})
.text(function (d) {
return d["id"].substring(d["id"].lastIndexOf(".") + 1);
});
// Do more D3 things
}
这起作用,我得到了相当不错的结果:角组件输出
,但我一直通过Angular讲出错误输出:
ERROR in src/app/grafo/grafo.component.ts(262,25): error TS2344: Type 'SVGPathSeg' does not satisfy the constraint 'BaseType'.
Type 'SVGPathSeg' is not assignable to type 'EnterElement'.
Property 'ownerDocument' is missing in type 'SVGPathSeg'.
phpstorm提示
指代码的这一部分:
let link = d3G.selectAll<SVGElement, any>(".link")
.data(root.links())
.enter()
.append<SVGPathSeg>("path")
.attr("class", "link")
.attr("d",radial);
我正在努力寻找解决方案,真的不知道是框架问题还是我的某个地方的错误。
tomwanzek在此问题上建议,我尝试用SVGPathElement
替换SVGPathSeg
,但这会触发一个错误,下面是.attr("d",radial)
的两行:
let link = d3G.selectAll<SVGElement, any>(".link")
.data(root.links())
.enter()
.append<SVGPathSeg>("path")
.attr("class", "link")
.attr("d",radial);
我之前使用的是SVGPathSeg
,因为它接受了.attr("d", radial)
。
https://ibb.co/g5cn0s
TS2345: Argument of type 'LinkRadial<any, DefaultLinkObject, [number,number]>' is not assignable to parameter of type 'ValueFn<SVGPathElement, HierarchyPointLink<{}>, string | number | boolean>'.
我错过了其他地方的某种类型?
,为了确保代码中的不同部分可以很好地播放,需要利用发电机(分层,树(和链接路径生成器上提供的一些通用物。
为了易于参考,假设您定义:
interface Datum {
id: string;
}
您的data
是类型Datum[]
然后,以下更改将确保使用兼容类型,以防止上述错误。
// ...
const stratify = d3.stratify<Datum>()
// ...
const tree = d3.tree<Datum>()
// ...
const radial = d3.linkRadial<HierarchyPointLink<Datum>, HierarchyPointNode<Datum>>()
请注意,HierarchyPointLink<Datum>
和HierarchyPointNode<Datum>
是树布局生成器创建的链接和节点类型,在类型Datum
的基础数据上使用。
当然,绑定的dom元素类型为 SVGPathElement
,即
let link = d3G.selectAll<SVGElement, any>(".link")
.data(root.links())
.enter()
.append<SVGPathElement>("path")
.attr("class", "link")
.attr("d", radial);