Angular和SVG:如何动态加载SVG组件?

时间:2018-11-30 21:21:17

标签: angular typescript svg

在我正在开发的应用程序中,我有命令列表(GC->圆,GB-> box,GE-> ellipse等)。我必须将它们渲染为SVG。

我遵循了指南https://angular.io/guide/dynamic-component-loader,但是关于SVG我缺少一些东西。

我为每个命令准备了一个组件(由于模板之外的代码相同,因此听起来有些愚蠢):

@Component({
  selector: '[app-gc]',
  template: '<svg:circle [attr.r]="command.diameter/2" [attr.stroke]="command.borderColor" fill="#000" [attr.stroke-width]="command.borderThickness" />'
})
export class GCComponent implements OnInit, SVGComponent {
  @Input('[command]') command: ZPL2.GraphicShapeBase;
  constructor() { }
}

加载渲染命令的组件如下所示:

@Component({
  selector: '[draggableSVGItem]',
  template: '<svg:g svg-host/>'
})
export class DraggableSvgItemComponent implements OnInit {      
  x: number = 0;
  y: number = 0;
  command: ZPL2.GraphicShapeBase;

  @Input()
  set draggableSVGItem(graphicCommand: ZPL2.GraphicShapeBase) {
    this.command = graphicCommand;
    this.x = graphicCommand.x;
    this.y = graphicCommand.y;
  }
  constructor() { }

  ngOnInit() {
    // Get the appropriate component for the command
    var componentType = null;
    if (this.command instanceof ZPL2.GC) {
      componentType = GCComponent;
    }
    if (this.command instanceof ZPL2.GB) {
      componentType = GBComponent;
    }
    if (this.command instanceof ZPL2.GE) {
      componentType = GEComponent;
    }

    // Get the component factory
    let componentFactory = this.componentFactoryResolver.resolveComponentFactory(componentType);

    // Clear the host view
    let viewContainerRef = this.svgHost.viewContainerRef;
    viewContainerRef.clear();

    // Dynamically create the component and set its command as the current one
    let componentRef = viewContainerRef.createComponent(componentFactory,);
    (<SVGComponent>componentRef.instance).command = this.command;
  }
}

一切正常。 我的问题是组件创建将SVG元素封装到DIV中,因此输出为空白:

extra div

我是Angular的新手,您是否有建议摆脱该DIV并使代码更简单?

编辑

我已通过以下链接上的示例解决了该问题:https://www.chrisjmendez.com/2017/06/17/angular-dynamically-inserting-svg-into-an-element/

通过绑定元素的innerHTML属性,我可以根据命令类类型设置不同的SVG内容:

模板:<svg:g [innerHTML]="svg"/>

ngOnInit() {
  // Get the appropriate component for the command
  var html = ``;
  if (this.command instanceof ZPL2.GC) {
    html = `<circle r="` + this.command.diameter / 2 + `" stroke="` + this.command.borderColor + `" fill="#000" stroke-width="` + this.command.borderThickness + `" />`;
  }
  if (this.command instanceof ...

  this.svg = this.sanitizer.bypassSecurityTrustHtml(html);
}

通过这种方式,我不需要为每个命令创建一个组件。每个命令可以有自己的getHTML()方法。

缺点是我没有绑定命令的属性,对吧?

1 个答案:

答案 0 :(得分:0)

我的动态加载svg文件的解决方案(对于同一组件):

在.html模板中(我使用下拉列表实现了该功能,但在此我剪切了该示例的代码):

<object *ngIf="currentSVG" type="image/svg+xml" [data]="SVGFile"></object>

在.ts文件中:

import { DomSanitizer, SafeUrl } from '@angular/platform-browser';

//component and class definition

SVGFile: SafeUrl;
currentSVG: string;

constructor(protected sanitizer: DomSanitizer) { ... }

//your code  

this.currentSVG = True;
this.SVGFile = this.sanitizer.bypassSecurityTrustResourceUrl('<your SVG file path>');

注意:SVG文件应位于资产目录中。