我正在创建一个使用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
&gt; g
。
我还尝试使用selector='svg:svg[foo]'
,然后创建svg:svg
元素并显示它。但是svg:svg
无法使用transform
属性移动,因此这对我的应用程序来说效果不佳。
如何为属性选择器组件动态创建svg:g
元素?
我使用的是Angular2:2.0.0-rc4。
答案 0 :(得分:3)
您确定了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解决之前,没有其他选择。
答案 1 :(得分:0)
我没有尝试使用Component Resolver创建组件到视图,而是改为使用。
希望它清楚并解决你的问题。
答案 2 :(得分:0)
我不确定我的解决方案是否正确,但是它对我有用(即使使用 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中。