Angular 2 - 如何在app.component中使用`svg`和将`circle`作为子组件?

时间:2017-08-23 17:38:18

标签: angular svg

所以我想使用Angular开发一个吃豆人游戏,我想使用 SVG ,我想创建一个嵌入{{1}的board.component }}

pacman.component将有一个board.component<svg></svg>会有一个pacman.component但角度会在<circle></circle> {/ p>}中引发此错误

[Angular]'circle'不是已知元素:

  
      
  1. 如果''是Angular组件,请验证它是否是此模块的一部分。
  2.   
  3. 允许任何元素将“ NO_ERRORS_SCHEMA ”添加到此组件的“ @ NgModule.schemas ”。
  4.   

修正这些错误后,我最终会使用 SVG

pacman.component

现在唯一的问题是角度将 <svg _ngcontent-c0="" width="100" height="100"> <app-pacman _ngcontent-c0="" _nghost-c1=""> <circle _ngcontent-c1="" fill="yellow" r="25" cx="10" cy="10"></circle> </app-pacman> </svg> pacman.component包裹起来,这会使<app-pacman></app-pacman>无效。

只是想知道Angular的做法是什么?我不希望将整个circle代码svg放在一个组件中。

感谢。

编辑:

(svg, circles, paths, etc...)

board.component.html

<svg [attr.width]="width" [attr.height]="height"> <app-pacman></app-pacman> </svg>

pacman.component.html

4 个答案:

答案 0 :(得分:6)

我相信回答您在这篇精彩文章中描述的问题:https://teropa.info/blog/2016/12/12/graphics-in-angular-2.html#avoiding-element-selectors-for-components

简而言之,您需要将子组件用作属性而不是元素(您可以这样做,因为@Component装饰器派生自@Directive)。 适用于您的情况,它看起来像这样:

在board.component.html中:

<svg [attr.width]="width" [attr.height]="height">
    <svg:g app-pacman />
</svg>

在pacman.component.ts中:

@Component({
    selector: '[app-pacman]',
    templateUrl: ...
})
...

答案 1 :(得分:1)

我认为你会想做这样的事情:

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

@Component({
    selector: 'svg-component',
    template: `
        <svg>
            <ng-content></ng-content>
        </svg>
    `
})
export class SvgComponent {}

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

@Component({
    selector: 'circle-component',
    template: `
        <ng-container>
            <circle></circle>
        </ng-container>
    `
})
export class CircleComponent {}

答案 2 :(得分:0)

SVG命名空间非常严格。我认为如果它包含未知元素,浏览器将完全拒绝svg。这是直接将svg注入DOM的原因之一,因为原始标记相对(但仍然不是非常)比注入其他类型的标记更安全。我和Svg一起工作很多角色,但想到这一点,我不认为我曾试图将他们的部分分成不同的角度成分。您可以尝试为组件使用不同的选择器,例如应用于常规svg元素的类或属性选择器。这可行。

我知道指令工作得很好。几乎所有我和元素都有相关的指令。我会尝试用指令完成你需要的东西 - 它们每个都可以保存主机的实例数据/属性,类似于一个组件,唯一的区别是视图全部封装在一个父组件中。您可以使用依赖项注入将主机/父组件注入所有子指令实例,或使用@ViewChildren查询所有子指令实例并从组件中操作它们。

如果您需要任意组合元素,可以使用svg group元素

    <g> ... </g> 

或者你可以使用有角度的&#39;隐形&#39;容器,

  <ng-container>...</ng-container> 

如果你需要做的就是迭代一些列表或者应用ngIf语句等等。

答案 3 :(得分:0)

我认为编译器错误[Angular] 'circle' is not a known element就是重点。只需将svg前缀添加到circle

<div [ngSwitch]="prop?.type">
    <app-svg-circle *ngSwitchCase="'circle'" [props]="prop"></app-svg-circle>
    <svg:path *ngSwitchCase="'path'" prop="prop"></svg:path>
</div>


@Component({
    selector: 'app-svg-base',
    template: `
            <svg:circle ${SvgBaseComponent.Bindings}></svg:circle>
    `
    })
    export class SvgBaseComponent {
      @Input()
      public props;
      public static readonly Bindings = '[attr.x]="props?.x" [attr.y]="props?.y" [attr.stroke]="props?.stroke"'

    }


@Component({
    selector: 'app-svg-circle',
    template: `
            <svg:circle ${SvgBaseComponent.Bindings}></svg:circle>
    `
    })
    export class SvgCircleComponent extends SvgBaseComponent { }