Angular 5中D3力导向图可视化无法居中问题求助
解决Angular 5中D3力导向图无法居中的问题
嘿,我帮你找到了问题的根源,咱们一步步把这个居中问题搞定:
核心问题:宽高获取错误导致居中失效
你代码里的let width = +this.svg.attr("width");和let height = +this.svg.attr("height");这两行有问题!因为你给SVG设置的是width="100%"和height="100%",用attr()拿到的是字符串"100%",转成数字后直接变成了NaN——这就相当于你让D3把图形居中到NaN/2, NaN/2的位置,完全起不到任何作用,难怪图形一直靠左!
解决方案:修正宽高获取+规范容器使用
下面是具体的修改步骤:
1. 给组件模板添加专用容器
首先在你的组件模板里(比如brain-page-home.component.html)加一个用来放SVG的容器,这样既符合Angular组件的规范,也能准确获取容器尺寸:
<div #svgContainer style="width: 100%; height: 100vh;"></div>
2. 在组件中获取容器引用并获取实际宽高
在组件类里添加ViewChild来获取容器元素,然后获取它的实际宽高:
import { ViewChild, ElementRef } from '@angular/core'; export class BrainPageHomeComponent implements OnInit, AfterViewInit, OnDestroy { @ViewChild('svgContainer') svgContainer: ElementRef; // ... 其他原有属性 //Load Brain public loadBrain() { d3.select("svg").remove(); this.brainService.getBrain().subscribe( data => { this.miserables = data['data']; // 获取容器实际宽高 const containerWidth = this.svgContainer.nativeElement.clientWidth; const containerHeight = this.svgContainer.nativeElement.clientHeight; // 将SVG添加到容器中,而不是body this.svg = d3.select(this.svgContainer.nativeElement) .append("svg") .attr("width", "100%") .attr("height", "100%") // 添加viewBox确保适配和居中 .attr("viewBox", `0 0 ${containerWidth} ${containerHeight}`) .attr("preserveAspectRatio", "xMidYMid meet") .call(d3.zoom().on("zoom", function () { let g = d3.select('svg > g'); g.attr("transform", d3.event.transform); })) .append("g"); // 用实际宽高设置居中力 this.simulation = d3.forceSimulation() .force("link", d3.forceLink().id(function (d) { return d.id; })) .force("charge", d3.forceManyBody()) .force("center", d3.forceCenter(containerWidth / 2, containerHeight / 2)); this.render(this.miserables); }, error => { console.log(error); }); } // ... 其他原有方法保持不变 }
3. 为什么之前的方法没生效?
你之前尝试的viewBox和重启simulation之所以没用,是因为:
viewBox需要正确的宽高数值才能生效,你之前没给它正确的参数;- 重启simulation但
forceCenter的参数是NaN,等于没设置居中规则,所以图形还是不会自动居中。
这样修改后,D3就能准确计算出容器的中心位置,把力导向图稳稳地放在中间啦!
内容的提问来源于stack exchange,提问作者Jérémie Chazelle
相关产品推荐
相关产品推荐

