我正在构建一个 Angular 应用程序 (Angular 4/5/6),并且想在我的组件模板中使用 SVG 精灵。
问题: 假设我已经生成了 SVG 图标精灵 (
icons.svg
),我怎样才能让 Angular 将我的 SVG 图标精灵注入/导入到我的组件模板中?
有没有一种方法可以将我的 SVG 图标精灵注入/导入到我的组件中,而无需使用任何第 3 方模块/指令,并使用 Angular 本身进行本地操作?
背景/问题:
如本文中所述,
icons.svg
文件将包含定义为<symbol>
的所有SVG图标。然后,我可以使用 <use>
在 HTML 中渲染选定的图标,假设 icons.svg
已注入到 DOM 中。
我使用 IcoMoon 应用程序生成了 SVG 精灵,并将
icons.svg
保存到我的 Angular 应用程序中。下面是我的示例 Angular 组件 (app.component.ts),我尝试在其中注入/导入 icons.svg
文件并尝试在 HTML 中渲染 SVG 图标。然而,Angular 并没有破坏我的 SVG 图标。我似乎错误地注入了 SVG 图标精灵文件。
更新:
icons.svg
,并让它在我使用它们时在 HTML 中呈现它们。app.component.ts:StackBlitz 上的实时示例:https://stackblitz.com/edit/angular-bbr2kh?file=src/app/app.component.ts
import { Component } from '@angular/core';
// import `./icons.svg`; // This import method doesn't work
@Component({
selector: 'my-app',
template: `
<!-- This import method doesn't work -->
<!-- <script src="./icons.svg"></script> -->
<p>
Hello this is a sample Angular 6 component.
</p>
<p>Testing to see if SVG icon sprite import works. See below if icons appear. </p>
<p>Icon (home): <svg class="icon icon-home"><use xlink:href="#icon-home"></use></svg> </p>
<p>Icon (rocket): <svg class="icon icon-rocket"><use xlink:href="#icon-rocket"></use></svg> </p>
<p>Icon (wifi): <svg class="icon icon-connection"><use xlink:href="#icon-connection"></use></svg>
<!-- This import method doesn't work -->
<!-- <p>Icon (home): <svg class="icon icon-home"><use xlink:href="./icons.svg#icon-home"></use></svg> </p>-->
</p>
`,
styles: [`
.icon {
display: inline-block;
width: 1em;
height: 1em;
stroke-width: 0;
stroke: currentColor;
fill: currentColor;
}
`]
})
export class AppComponent {
}
我认为你的根源路径是你遇到问题的地方。在您的代码中,您告诉 Angular 查看
app
但浏览器将其视为 https://your-site.com./icons
如果您将图标文件移动到
/assets
文件夹下,那么它应该已经可用,因为 src\assets
文件夹已包含在 angular.json
中,"assets"
集合告诉 Angular 在哪里查找。
<svg class="icon">
<use xlink:href="/assets/icons.svg#icon-rocket"></use> // Notice root path not "./"
</svg>
如果您希望从另一个目录提供文件,您需要做的就是在 angular.json 中添加一个路径:
…
"assets": [
"src/favicon.ico",
"src/assets",
"src/your-dir"
],
…
然后在你的代码中
<svg class="icon">
<use xlink:href="/your-dir/icons.svg#icon-rocket"></use>
</svg>
我不建议添加
/src/app
作为资产路径,这基本上会打开您的整个应用程序来提供文件,使您的整个目录可访问。
我分叉了你的示例并更新了here
我使用角度材质图标解决了这个问题。
Angular 材质通过 id 注入 SVG,无需 shadow-dom。
首先安装角材:
"@angular/material": "^7.3.7", // change version according to your angular version
导入到您的模块:
MatIconModule
然后在 app.component 或 service 中声明你的 SVG sprite..
constructor(
private matIconRegistry: MatIconRegistry,
private domSanitizer: DomSanitizer) {
matIconRegistry.addSvgIconSet(this.domSanitizer.bypassSecurityTrustResourceUrl(`assets/sprite.svg`));
}
最后,在 Html 中使用角度材质图标:
<mat-icon svgIcon="svg-id"></mat-icon> // or use as directive <div svgIcon="svg-id"></div>
您可以通过https://icomoon.io/app/#/select将您的svg文件转换为字体,上传您的svg文件并选择它,单击生成字体然后单击下载按钮, 下载字体文件并选择字体文件夹并将其放入项目中的文件夹中,
将字体文件导入到css文件中
@font-face {
font-family: 'icomoon';
src: url('fonts/icomoon.eot?31svmk');
src: url('fonts/icomoon.eot?31svmk#iefix') format('embedded-opentype'),
url('fonts/icomoon.ttf?31svmk') format('truetype'),
url('fonts/icomoon.woff?31svmk') format('woff'),
url('fonts/icomoon.svg?31svmk#icomoon') format('svg');
font-weight: normal;
font-style: normal;
}
像这样声明你的类
.icon-home:before {
content: "\ea77";
}
.icon-conection:before {
content: "\ea78";
}
.icon-rocket:before {
content: "\ea79";
}
并在你的html中使用它
<p>Icon (rocket): <i class="icon-rocket"></i> </p>
解决方案是在项目中添加图标,但是如果你想在项目中使用svg代码,最好添加loader。
如果你使用过webpack:
npm install svg-inline-loader --save-dev
只需像这样将配置对象添加到 module.loaders 即可。
{
test: /\.svg$/,
loader: 'svg-inline-loader'
}
我遇到了类似的问题,并使用与给出的一些答案类似的技术解决了问题。根据需要使用此选项以及可选的高度和宽度设置...
<app-icon icon="filter" width="15" height="15"></app-icon>
或
<app-icon icon="filter"></app-icon>
该组件在
icon.component.svg
中只有两个图标(我目前正在使用的所有图标):
<!-- https://icons.getbootstrap.com/ -->
<div [ngSwitch]="icon">
<svg *ngSwitchCase="'filter'" xmlns="http://www.w3.org/2000/svg" [attr.width]="width" [attr.height]="height" fill="currentColor" viewBox="0 0 16 16">
<path d="M1.5 1.5A.5.5 0 0 1 2 1h12a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.128.334L10 8.692V13.5a.5.5 0 0 1-.342.474l-3 1A.5.5 0 0 1 6 14.5V8.692L1.628 3.834A.5.5 0 0 1 1.5 3.5v-2zm1 .5v1.308l4.372 4.858A.5.5 0 0 1 7 8.5v5.306l2-.666V8.5a.5.5 0 0 1 .128-.334L13.5 3.308V2h-11z"/>
</svg>
<svg *ngSwitchCase="'tags'" xmlns="http://www.w3.org/2000/svg" [attr.width]="width" [attr.height]="height" fill="currentColor" viewBox="0 0 16 16">
<path d="M3 2v4.586l7 7L14.586 9l-7-7H3zM2 2a1 1 0 0 1 1-1h4.586a1 1 0 0 1 .707.293l7 7a1 1 0 0 1 0 1.414l-4.586 4.586a1 1 0 0 1-1.414 0l-7-7A1 1 0 0 1 2 6.586V2z"/>
<path d="M5.5 5a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm0 1a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zM1 7.086a1 1 0 0 0 .293.707L8.75 15.25l-.043.043a1 1 0 0 1-1.414 0l-7-7A1 1 0 0 1 0 7.586V3a1 1 0 0 1 1-1v5.086z"/>
</svg>
</div>
和
icon.component.ts
:
import { Component, Input, OnInit } from '@angular/core';
@Component({
selector: 'app-icon',
templateUrl: './icon.component.svg',
styleUrls: []
})
export class IconComponent implements OnInit{
@Input() icon: any
@Input() width?: any
@Input() height?: any
ngOnInit(): void {
if (typeof this.width != 'string') {
this.width = '20'
}
if (typeof this.height != 'string') {
this.height = '20'
}
}
}
无需包含整个图标库集,在应用程序中重复使用相当简单。
3年前我写了一篇关于它的文章。看看是否有帮助:Material Design Icons:Font vs SVG。以及如何在 Angular 中使用 SVG Sprites?
今天我也和你一样,设计师们反对 svg 字体。我也不想将图标定义移出node_modules,因为它会随着时间的推移而改变。我想出了一个解决方案。
您需要首先创建一个角度图标组件,然后执行如下操作:
import { Component, OnInit, Input } from '@angular/core';
declare const require;
@Component({
selector: 'my-icon',
templateUrl: './my-icon.component.html',
styleUrls: ['./my-icon.component.scss']
})
export class IconComponent implements OnInit {
constructor() { }
@Input() icon: string = "";
@Input() x: string = "0";
@Input() y: string = "0";
@Input() fillColor: string = "black";
@Input() strokeColor: string = "black";
@Input() height: string = "";
@Input() width: string = "";
private baseUrl: string = require("../../../../../node_modules/path/to/defs.svg") + "#beginning-of-iconset-";
svgUrl: string = "";
ngOnInit() {
}
ngAfterViewInit() {
setTimeout(()=>{
this.svgUrl = this.baseUrl + this.icon;
},0);
}
}
然后,在 html 中:
<svg [attr.height]="height" [attr.width]="width" xmlns="http://www.w3.org/2000/svg">
<use [attr.href]="svgUrl" [attr.x]="x" [attr.y]="y" [attr.fill]="fillColor" [attr.stroke]="strokeColor" />
</svg>
我仍在努力扩展解决方案,因为宽度和高度属性未按预期工作。您还可以扩展输入,我知道我会的。
希望有帮助。