首页 > 解决方案 > 如何正确测量 Angular 中的 svg 组尺寸?

问题描述

我正在尝试在 Angular 的帮助下构建一个工具来可视化类似于 TensorBoard 的图形。我的目的是可视化构建工具 bazel 输出的依赖关系图。为了突出显示图形,我想绘制一个矩形作为背景。我目前的方法是在一组中绘制节点和边缘,测量组的尺寸并相应地设置矩形的宽度和高度。如果我通过扩展或最小化节点来更改图形结构,则背景矩形不会正确更新。我猜这是因为没有对组件数据进行任何更改,因此 Angular 不会更新视图。

您将在此处找到源代码:https ://github.com/dprogm/graph-explorer

图表的模板如下所示:

<svg:rect
  attr.width="{{_graph.width}}"
  attr.height="{{_graph.height}}" />

<svg:g #graphRef>
  <svg:path  *ngFor="let edge of _graph.edges"
    class="edge"
    [attr.d]="buildPath(edge)" />

  <svg:g app-graph-node *ngFor="let node of _graph.nodes"
    [node]="node"
    (nodeChange)="onNodeChanged($event)"></svg:g>
</svg:g>

#graphRefElementRef用于查询边界框的:

if(this.graphRef !== undefined) {
  let graphBBox = this.graphRef.nativeElement.getBBox();
  this._graph.width = graphBBox.width;
  this._graph.height = graphBBox.height;
}

主要问题是:有没有更好的方法来测量图表的大小,如果没有,我怎样才能获得正确的尺寸?

在最小化子图节点之前

最小化子图节点后

您可以在此处重现该问题:https ://stackblitz.com/edit/angular-ivy-mkmkm6?file=src/app/app.component.html 如果单击圆圈,它会更改大小。我希望黑色矩形也改变它的大小以适应圆圈。

标签: htmlangularsvggraphtensorboard

解决方案


一种方法是使用requestAnimationFrame()

import { Component, ElementRef, ViewChild, AfterViewInit, VERSION } from '@angular/core';
import { Observable } from 'rxjs';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements AfterViewInit  {

  // Background width
  bgWidth = 0;
  // Background height
  bgHeight = 0;
  // Radius of the circle
  r = 100;
  // Stroke width of the circle
  strokeWidth = 5;
  // Whether to draw a large or small circle
  largeMode: Boolean = true;

  @ViewChild('groupRef')
  groupRef : ElementRef;

  ngAfterViewInit(): void {
    requestAnimationFrame(()=> this.setRectSize());
  }

  setRectSize(): void {
    let groupBBox = this.groupRef.nativeElement.getBBox();
    this.bgWidth = groupBBox.width;
    this.bgHeight = groupBBox.height;
  }

  changeSize() : void {
    this.largeMode = !this.largeMode;
    if(this.largeMode) {
      this.r = 100;
    } else {
      this.r = 50;
    }
    requestAnimationFrame(()=> this.setRectSize());
  }
}

推荐阅读