Angularアプリケーション(Angular 4/5/6)を構築していて、コンポーネントテンプレートでSVGスプライトを使用したいと思います。
質問:SVGアイコンスプライトがすでに生成されていると仮定すると(icons.svg
)、どうすればAngular = SVGアイコンスプライトをコンポーネントのテンプレートに挿入/インポートするには?
サードパーティのモジュール/ディレクティブを使用せずにSVGアイコンスプライトをコンポーネントに挿入/インポートし、Angular自体でネイティブに実行する方法はありますか?
背景/問題:
この記事 で説明したように、icons.svg
ファイルには<symbol>
として定義されたすべてのSVGアイコンが含まれます。次に、<use>
がDOMに挿入されていると仮定して、icons.svg
を使用してHTMLで選択したアイコンをレンダリングできます。
IcoMoon app を使用して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
を追加することはお勧めしません。これにより、基本的にアプリ全体がファイルを提供できるようになり、ディレクトリ全体にアクセスできるようになります。
私はあなたの例をフォークして更新しました ここ
angularマテリアルアイコンを使用してこの問題を解決しました。
AngularマテリアルはSVGをIDで、shadow-domなしで注入します。
最初のインストールangularマテリアル:
"@angular/material": "^7.3.7", // change version according to your angular version
モジュールにインポートします。
MatIconModule
次に、app.componentまたはserviceでSVGスプライトを宣言します。
constructor(
private matIconRegistry: MatIconRegistry,
private domSanitizer: DomSanitizer) {
matIconRegistry.addSvgIconSet(this.domSanitizer.bypassSecurityTrustResourceUrl(`assets/Sprite.svg`));
}
そして最後に、HTMLでangularマテリアルアイコン:
<mat-icon svgIcon="svg-id"></mat-icon> // or use as directive <div svgIcon="svg-id"></div>
私は今日あなたと同じ船に乗っており、デザイナーが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ファイルをフォントに変換するには 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コードを使用する場合は、ローダーをプロジェクトに追加することをお勧めします。
Webpackを使用したことがある場合:
npm install svg-inline-loader --save-dev
このように、構成オブジェクトをmodule.loadersに追加するだけです。
{
test: /\.svg$/,
loader: 'svg-inline-loader'
}