[英]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 為視圖創建組件,而是這樣做。
希望它清楚並解決您的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.