簡體   English   中英

如何在 Angular2 中動態創建 SVG 組件?

[英]How to create an SVG component dynamically in Angular2?

我正在創建一個使用 SVG 的 Web 應用程序。 我創建了由 SVG 元素組成的組件,並將它們放入根svg元素中。 他們有屬性選擇器,因為 SVG/XML 文檔樹很嚴格,所以我不能使用元素選擇器。 他們有一個以svg:g標簽開頭的模板:

@Component({
  selector:'[foo]',
  template: '<svg:g>...</svg:g>',
})

在應用程序中,我想在用戶按下按鈕時創建一個組件,並同時開始拖動它。 我認為可以通過使用ComponentResolver動態創建組件來實現:

  @ViewChild('dynamicContentPlaceHolder', {read: ViewContainerRef})
  protected dynamicComponentTarget: ViewContainerRef

  private componentResolver: ComponentResolver

  onMouseDown() {
    this.componentResolver
      .resolveComponent(FooComponent)
      .then((factory) => {
        const dynamicComponent = this.dynamicComponentTarget.createComponent(factory, 0)
        const component: FooComponent = dynamicComponent.instance
        const element = dynamicComponent.location.nativeElement
        // add event listener to start dragging `element`.
      })
  }

組件是在onMouseDown()調用時創建的,但是它的 DOM 元素是div ,所以它是 svg 文檔中的非法元素,無法顯示。

我嘗試過使用selector='svg:g[foo]' ,然后創建了g元素,但它的命名空間不是用於 SVG ( http://www.w3.org/2000/svg ),而是普通的 HTML 命名空間 ( http://www.w3.org/1999/xhtml ),它的類是HTMLUnknownElement > g

我也嘗試過使用selector='svg:svg[foo]' ,然后創建svg:svg元素並顯示它。 但是svg:svg不能使用transform屬性移動,所以這對我的應用程序來說效果不佳。

如何為屬性選擇器組件動態創建svg:g元素?

我正在使用 Angular2:2.0.0-rc4。

您是正確的關於使g元素無法呈現為svg的命名空間問題。 不幸的是,將節點附加為一個 svg 元素是使組件正確地進入命名空間的唯一方法。

但是,這並不意味着這不起作用。 如果您在模板中的 g 元素上添加拖動功能作為指令,它將與您的組件一起編譯,您可以將您的邏輯偏移到該指令中。 頂級 svg 將被正確命名,模板將相應地繼承它。

import {Component, Input} from '@angular/core';

@Component({
  selector: 'svg:svg[customName]', // prevent this from hijacking other svg
  template: '<svg:g dragDirective>...</svg:g>', // note the directive added here
  style: []
})
export class GComponent {

  constructor() { }

}

這可能並不理想,但在解決https://github.com/angular/angular/issues/10404之前,沒有太多替代方案。

我不確定我的解決方案是否正確,但它對我有用(即使使用ivy ):

@Component({
...
})
class ParentComponent {
    constructor(
        private injector: Injector,
        private appRef: ApplicationRef,
        private componentFactoryResolver: ComponentFactoryResolver,
    ) {}

    createDynamicComponent() {
        let node = document.createElementNS("http://www.w3.org/2000/svg", "svg");
        let factory = this.componentFactoryResolver.resolveComponentFactory(DynamicComponent);
        let componentRef = factory.create(this.injector, [], node);

        this.appRef.attachView(componentRef.hostView);
    }
}

之后,您必須手動將node附加到 DOM 中。

我不會嘗試使用 Component Resolver 為視圖創建組件,而是這樣做。

  • 創建一個對象,其屬性與要傳遞給 SVG 組件的屬性相匹配。
  • 將此對象附加到數組(例如.svgItems)。
  • 將 *ngFor="svgItem in svgItems" 添加到要動態創建的 SVG 組件。

希望它清楚並解決您的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM