Я создаю приложение Angular (Angular 4/5/6) и хотел бы использовать спрайты SVG в моем шаблоне компонента.
Вопрос:
Предполагая, что у меня уже есть сгенерированный спрайт значка SVG (icons.svg), как я могу заставить Angular вставлять / импортировать мой спрайт значка SVG в шаблон моего компонента?
Есть ли способ внедрить / импортировать мой спрайт значка SVG в мой компонент без использования каких-либо сторонних модулей / директив и сделать это изначально с помощью самого Angular?
Справочная информация / проблема:
Как обсуждалось в эта статья, файл icons.svg будет содержать все значки SVG, определенные как <symbol>. Затем я могу отобразить выбранные значки в моем HTML с помощью <use>, предполагая, что icons.svg внедрен в DOM.
Я сгенерировал SVG-спрайты с помощью Приложение IcoMoon и сохранил icons.svg в моем приложении Angular. Ниже приведен мой образец компонента Angular (app.component.ts), в котором я пытаюсь внедрить / импортировать файл icons.svg и отобразить значки SVG в моем HTML. Однако 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 {
}





вы можете преобразовать свой файл svg в шрифт с помощью https://icomoon.io/app/#/select, загрузить свой файл 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, лучше всего добавить к нему загрузчик.
Если вы использовали веб-пакет:
npm install svg-inline-loader --save-dev
Просто добавьте объект конфигурации в module.loaders следующим образом.
{
test: /\.svg$/,
loader: 'svg-inline-loader'
}
Приятно знать, что я могу конвертировать свои SVG-спрайты в шрифты, однако я не думаю, что это реальное решение. Почему я не могу напрямую использовать сами спрайты SVG? Почему я должен обойти главную проблему?
У меня уже была эта проблема, и мне пришлось использовать это решение, этот метод решает вашу проблему. Если у вас нет другой причины использовать svg в Angular
Если вы используете WebPack, вы можете решить свою проблему, добавив загрузчик, я добавляю объяснение в тексте выше. я надеюсь, что это поможет тебе
Я не понимаю, почему мы должны использовать обходной путь «CSS / Font» вместо возможности напрямую использовать SVG. Это ошибка в Angular? Разве Angular недостаточно гибкости для поддержки основных функций, таких как возможность загрузки внешних файлов?
@AlirezaVarmaghani при создании производственной сборки напрямую добавляет файл в его корень (svgs и шрифты). Он должен напрямую импортироваться в сам CSS.
Я думаю, что ваш корневой путь - это то место, где у вас возникают проблемы. В вашем коде вы указываете 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 в качестве пути к ресурсам, это в основном открыло бы все ваше приложение для обслуживания файлов, сделав доступным весь ваш каталог.
Раздвоил твой пример и обновил здесь
Если я использую значки из спрайта SVG на нескольких экранах, тогда это будет отдельный сетевой вызов для спрайта для визуализации отдельного значка, не так ли? Есть ли способ ограничить этот вызов до одного раза при загрузке приложения?
@parthsw Если вы хотите загрузить все спрайты при загрузке, я бы сохранил все спрайты в одном файле эта статья объясняет это довольно хорошо, короче говоря, вы добавляете все спрайты как символы в один файл svg, а затем используйте его как <svg><use xlink:href = "assets/svgSprites.svg#spriteID"></use></svg>
Сегодня я был в той же лодке, когда дизайнеры возражали против шрифта svg. Я также не хотел перемещать значок def из node_modules, потому что со временем он будет меняться. Я придумал решение.
Вам нужно сначала создать компонент значка angular, а затем сделать что-то вроде этого:
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>
Я все еще работаю над масштабированием решения, поскольку атрибуты ширины и высоты работают не так, как ожидалось. Вы также можете расширить входные данные, насколько я знаю.
Надеюсь, это поможет.
Я решил эту проблему, используя угловой значок материала.
Угловой материал вводит SVG по идентификатору и без теневой дом.
Сначала установите угловой материал:
"@angular/material": "^7.3.7", // change version according to your angular version
Импортируйте в свой модуль:
MatIconModule
Затем объявите свой SVG-спрайт в приложении или сервисе.
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>
Создайте компонент my-icon, который принимает ссылку на вашу таблицу спрайтов для @input. Проверь это ... Stackblitz