如何将 svg 从文件导入到 angular 5 中的组件?
How do I import svg from file to a component in angular 5?
我发现所有将 svg 添加到 AngularCli 中的组件的教程都建议将其插入 html 模板中,如下所示:
<div>
<svg viewBox="0 0 250 250">
<svg:g class="group">
<svg:polygon class="shield" points="125,30 125,30 125,30 31.9,63.2 46.1,186.3 125,230 125,230 125,230 203.9,186.3 218.1,63.2" />
<svg:path class="a" d="M125,52.1L66.8,182.6h0h21.7h0l11.7-29.2h49.4l11.7,29.2h0h21.7h0L125,52.1L125,52.1L125,52.1L125,52.1
L125,52.1z M142,135.4H108l17-40.9L142,135.4z"/>
</svg:g>
</svg>
</div>
但我希望保持模板清晰,只在其中插入几个带有 url 的标签以分隔 svg 文件,somwehow 是这样的:
<svg class="star">
<use xlink:href="../../../assets/images/svg/star.svg"
x="0"
y="0" />
</svg>
如何在组件中使用单独的 svg 文件?
将您的 SVG 文件包含在 src/assets 文件夹中,并将 svg 文件夹添加到您的 angular.json
文件中。
"assets": [ "src/assets/svg/*" ]
这样您就可以根据需要将文件包含在您的组件中。
一种方法是为您的 svg 文件设置 id 属性 并将您的 svg 文件放在您的资产文件夹中。然后像这样在 mat-icon 中使用该 id:
<mat-icon svgIcon="my-star-icon"></mat-icon>
这是一种更好的方法;通过这种方式,您不必在 UI html 代码中处理 svg 标签。这也支持 google 图标。
不过如果您使用 angular material,这会起作用。
编辑:
您需要在组件中使用 IconRegistry 注册图标才能工作:
constructor(iconRegistry: MatIconRegistry, sanitizer: DomSanitizer) {
iconRegistry.addSvgIcon(
'my-star-icon',
sanitizer.bypassSecurityTrustResourceUrl('assets/icons/my-star-icon.svg'));
}
如果你有 logo.svg
:
- 将其放入您的
src/assets
文件夹
- 在
angular.json
配置中包含文件夹:"assets": [ "src/assets" ]
- 从模板中引用:
<img src="assets/svg/logo.svg">
所以我一直在尝试这样做,在我的一生中,我无法让这个 svg 显示出来,直到......经过多次互联网搜索,我认为不只是我,如果你从互联网上复制意大利面路径然后也许你忘了包括这个
xmlns="http://www.w3.org/2000/svg"
<svg xmlns="http://www.w3.org/2000/svg" height="100" width="100">
<path d="I love copying and pasting paths"/>
</svg>
然后你可以继续做你的
<img src="assets/img/logo.svg" />
如果这不起作用,并且您想以某种方式处理图像,那么请将图像放入
assets/img/copypasta.png
1在此处输入代码`在这里,我尝试了类似这些的更改方式,首先创建了一个 .ts 文件作为 iconpack 并将其导出。
`导出常量ICON_PACK_6 = {
'VNF-pkg': '<svg fill="#222b45b8" id="Layer_5" enable-background="new 0 0 64 64" height="24" viewBox="0 0 64 64" width="24" xmlns="http://www.w3.org/2000/svg"><g><path d="m42.929 49h14.142v2h-14.142z" transform="matrix(.142 -.99 .99 .142 -6.577 92.415)"/><path d="m52.293 47.707 2.293 2.293-2.293 2.293 1.414 1.414 3.707-3.707-3.707-3.707z"/><path d="m46.293 46.293-3.707 3.707 3.707 3.707 1.414-1.414-2.293-2.293 2.293-2.293z"/><path d="m60.884/><path d="m41 17h14v2h-14z"/></g></svg>',
};`
之后在构造函数中调用应用程序组件中的函数,如下所示
this.iconLibraries.registerSvgPack('pack-6', ICON_PACK_6);
当来到星云菜单时添加
{title: "VNF Onboarding",link: "/package-management/view", icon: { icon: 'VNF-pkg', pack: 'pack-6' }, },
]
Output
还有一种更优雅的方法,但是它意味着 svg 文件具有与文件名相同的 ID。
Svg 组件:
import { Component, Input, OnInit } from '@angular/core';
@Component({
selector: 'app-svg-icon',
template: '
<svg attr.width="{{width}}px" attr.height="{{height}}px" attr.fill="{{fill}}" attr.class="{{class}}">
<use attr.xlink:href="assets/icons/{{icon}}.svg#{{icon}}"></use>
</svg>
',
})
export class SvgIconComponent implements OnInit {
@Input() icon!: string;
@Input() width?: number;
@Input() height?: number;
@Input() size?: number = 24;
@Input() fill?: string;
@Input() class?: string;
ngOnInit(): void {
if (!this.width || !this.height) {
this.width = this.size;
this.height = this.size;
}
}
}
假设您的文件夹中有 svg:/assets/icons/person.svg
svg 本身包含以下代码(以便您可以轻松更改 svg 的大小和颜色,它不应包含高度、宽度和填充属性):
<svg id="person" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M12 5.9c1.16 0 2.1.94 2.1 2.1s-.94 2.1-2.1 2.1S9.9 9.16 9.9 8s.94-2.1 2.1-2.1m0 9c2.97 0 6.1 1.46 6.1 2.1v1.1H5.9V17c0-.64 3.13-2.1 6.1-2.1M12 4C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 9c-2.67 0-8 1.34-8 4v3h16v-3c0-2.66-5.33-4-8-4z" />
</svg>
现在您可以在任何组件中使用您的图标了:
<app-svg-icon [icon]="'person'" fill="red" [size]="48"></app-svg-icon>
TL;DR,使用 HttpClient
获取文件,然后使用 bypassSecurityTrustHtml
用 [innerHTML]
渲染它。
这可能有点晚了,但我们是这样找到解决方案的。我们尝试查看 angular material 如何为他们的图标做这件事,天哪,我们惊讶于它真的如此简单。他们只是使用 HttpClient
获取文件!它已经在我们的脑海中,但我们一直忽略它,因为我们认为也许有更好的解决方案。
经过几分钟的搜索,我们偶然发现了这个:
https://github.com/angular/components/blob/653457eaf48faab99227f37bc2fe104d9f308787/src/material/icon/icon-registry.ts#L621
所以基本上,如果您的 SVG 文件位于资产文件夹 (/assets/images/svg/star.svg
) 中,您所要做的就是使用 HttpClient.get
获取它并使用 DomSanitizer
绕过安全性并相信给定值是安全的 HTML,然后才能将其呈现给您的组件。
最后,我们的组件如下所示:
import { Component, OnInit, SecurityContext } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { DomSanitizer } from '@angular/platform-browser';
@Component({
selector: 'app-svg-icon',
template: `<span [innerHTML]="svgIcon"></span>`,
styleUrls: ['./svg-icon.component.scss'],
})
export class SvgIconComponent implements OnInit {
@Input()
public name?: string;
public svgIcon: any;
constructor(
private httpClient: HttpClient,
private sanitizer: DomSanitizer,
) {
}
public ngOnInit(): void {
this.httpClient
.get(`assets/images/svg/${this.name}.svg`, { responseType: 'text' })
.subscribe(value => {
this.svgIcon = this.sanitizer.bypassSecurityTrustHtml(value);
});
}
}
现在您只需将组件导入应用中的任何位置即可
<app-svg-icon name="star"></app-svg-icon>
我发现所有将 svg 添加到 AngularCli 中的组件的教程都建议将其插入 html 模板中,如下所示:
<div>
<svg viewBox="0 0 250 250">
<svg:g class="group">
<svg:polygon class="shield" points="125,30 125,30 125,30 31.9,63.2 46.1,186.3 125,230 125,230 125,230 203.9,186.3 218.1,63.2" />
<svg:path class="a" d="M125,52.1L66.8,182.6h0h21.7h0l11.7-29.2h49.4l11.7,29.2h0h21.7h0L125,52.1L125,52.1L125,52.1L125,52.1
L125,52.1z M142,135.4H108l17-40.9L142,135.4z"/>
</svg:g>
</svg>
</div>
但我希望保持模板清晰,只在其中插入几个带有 url 的标签以分隔 svg 文件,somwehow 是这样的:
<svg class="star">
<use xlink:href="../../../assets/images/svg/star.svg"
x="0"
y="0" />
</svg>
如何在组件中使用单独的 svg 文件?
将您的 SVG 文件包含在 src/assets 文件夹中,并将 svg 文件夹添加到您的 angular.json
文件中。
"assets": [ "src/assets/svg/*" ]
这样您就可以根据需要将文件包含在您的组件中。
一种方法是为您的 svg 文件设置 id 属性 并将您的 svg 文件放在您的资产文件夹中。然后像这样在 mat-icon 中使用该 id:
<mat-icon svgIcon="my-star-icon"></mat-icon>
这是一种更好的方法;通过这种方式,您不必在 UI html 代码中处理 svg 标签。这也支持 google 图标。
不过如果您使用 angular material,这会起作用。
编辑: 您需要在组件中使用 IconRegistry 注册图标才能工作:
constructor(iconRegistry: MatIconRegistry, sanitizer: DomSanitizer) {
iconRegistry.addSvgIcon(
'my-star-icon',
sanitizer.bypassSecurityTrustResourceUrl('assets/icons/my-star-icon.svg'));
}
如果你有 logo.svg
:
- 将其放入您的
src/assets
文件夹 - 在
angular.json
配置中包含文件夹:"assets": [ "src/assets" ]
- 从模板中引用:
<img src="assets/svg/logo.svg">
所以我一直在尝试这样做,在我的一生中,我无法让这个 svg 显示出来,直到......经过多次互联网搜索,我认为不只是我,如果你从互联网上复制意大利面路径然后也许你忘了包括这个
xmlns="http://www.w3.org/2000/svg"
<svg xmlns="http://www.w3.org/2000/svg" height="100" width="100">
<path d="I love copying and pasting paths"/>
</svg>
然后你可以继续做你的
<img src="assets/img/logo.svg" />
如果这不起作用,并且您想以某种方式处理图像,那么请将图像放入
assets/img/copypasta.png
1在此处输入代码`在这里,我尝试了类似这些的更改方式,首先创建了一个 .ts 文件作为 iconpack 并将其导出。
`导出常量ICON_PACK_6 = {
'VNF-pkg': '<svg fill="#222b45b8" id="Layer_5" enable-background="new 0 0 64 64" height="24" viewBox="0 0 64 64" width="24" xmlns="http://www.w3.org/2000/svg"><g><path d="m42.929 49h14.142v2h-14.142z" transform="matrix(.142 -.99 .99 .142 -6.577 92.415)"/><path d="m52.293 47.707 2.293 2.293-2.293 2.293 1.414 1.414 3.707-3.707-3.707-3.707z"/><path d="m46.293 46.293-3.707 3.707 3.707 3.707 1.414-1.414-2.293-2.293 2.293-2.293z"/><path d="m60.884/><path d="m41 17h14v2h-14z"/></g></svg>',
};`
之后在构造函数中调用应用程序组件中的函数,如下所示
this.iconLibraries.registerSvgPack('pack-6', ICON_PACK_6);
当来到星云菜单时添加
{title: "VNF Onboarding",link: "/package-management/view", icon: { icon: 'VNF-pkg', pack: 'pack-6' }, },
]
Output
还有一种更优雅的方法,但是它意味着 svg 文件具有与文件名相同的 ID。
Svg 组件:
import { Component, Input, OnInit } from '@angular/core';
@Component({
selector: 'app-svg-icon',
template: '
<svg attr.width="{{width}}px" attr.height="{{height}}px" attr.fill="{{fill}}" attr.class="{{class}}">
<use attr.xlink:href="assets/icons/{{icon}}.svg#{{icon}}"></use>
</svg>
',
})
export class SvgIconComponent implements OnInit {
@Input() icon!: string;
@Input() width?: number;
@Input() height?: number;
@Input() size?: number = 24;
@Input() fill?: string;
@Input() class?: string;
ngOnInit(): void {
if (!this.width || !this.height) {
this.width = this.size;
this.height = this.size;
}
}
}
假设您的文件夹中有 svg:/assets/icons/person.svg
svg 本身包含以下代码(以便您可以轻松更改 svg 的大小和颜色,它不应包含高度、宽度和填充属性):
<svg id="person" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M12 5.9c1.16 0 2.1.94 2.1 2.1s-.94 2.1-2.1 2.1S9.9 9.16 9.9 8s.94-2.1 2.1-2.1m0 9c2.97 0 6.1 1.46 6.1 2.1v1.1H5.9V17c0-.64 3.13-2.1 6.1-2.1M12 4C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 9c-2.67 0-8 1.34-8 4v3h16v-3c0-2.66-5.33-4-8-4z" />
</svg>
现在您可以在任何组件中使用您的图标了:
<app-svg-icon [icon]="'person'" fill="red" [size]="48"></app-svg-icon>
TL;DR,使用 HttpClient
获取文件,然后使用 bypassSecurityTrustHtml
用 [innerHTML]
渲染它。
这可能有点晚了,但我们是这样找到解决方案的。我们尝试查看 angular material 如何为他们的图标做这件事,天哪,我们惊讶于它真的如此简单。他们只是使用 HttpClient
获取文件!它已经在我们的脑海中,但我们一直忽略它,因为我们认为也许有更好的解决方案。
经过几分钟的搜索,我们偶然发现了这个: https://github.com/angular/components/blob/653457eaf48faab99227f37bc2fe104d9f308787/src/material/icon/icon-registry.ts#L621
所以基本上,如果您的 SVG 文件位于资产文件夹 (/assets/images/svg/star.svg
) 中,您所要做的就是使用 HttpClient.get
获取它并使用 DomSanitizer
绕过安全性并相信给定值是安全的 HTML,然后才能将其呈现给您的组件。
最后,我们的组件如下所示:
import { Component, OnInit, SecurityContext } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { DomSanitizer } from '@angular/platform-browser';
@Component({
selector: 'app-svg-icon',
template: `<span [innerHTML]="svgIcon"></span>`,
styleUrls: ['./svg-icon.component.scss'],
})
export class SvgIconComponent implements OnInit {
@Input()
public name?: string;
public svgIcon: any;
constructor(
private httpClient: HttpClient,
private sanitizer: DomSanitizer,
) {
}
public ngOnInit(): void {
this.httpClient
.get(`assets/images/svg/${this.name}.svg`, { responseType: 'text' })
.subscribe(value => {
this.svgIcon = this.sanitizer.bypassSecurityTrustHtml(value);
});
}
}
现在您只需将组件导入应用中的任何位置即可
<app-svg-icon name="star"></app-svg-icon>