web-dev-qa-db-ja.com

AngularコンポーネントHTMLDOMにSVGアイコンスプライトを挿入する方法は?

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.tsicons.svgファイルを挿入/インポートし、HTMLでSVGアイコンをレンダリングしようとしています。ただし、 AngularはSVGアイコンをレンダリングしていません。SVGアイコンのスプライトファイルを誤って挿入しているようです。

更新:

  1. 私はすでに同様の質問を知っています angular-cliを使用したSVGアイコンシステム 、ここで提案された答えはNodeモジュールを使用することでした svg-SpriteCSSモードを使用してSVGスプライトを生成します。ただし、これは私が求めているものではありません。SVGスプライトを生成しようとはしていません。get=を試みています。 Angularコンポーネントは、私のSVGスプライトicons.svgを認識し、使用するたびにHTMLでレンダリングするようにします。
  2. SVGスプライトからCSSフォントを生成するための解決策が提案されました https://stackoverflow.com/a/50460361/498801 。これは実行可能な解決策ではなく、SVGスプライトを使用できないようにするための「回避策」であると私は感じています。

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 {
}
4
Zythyr

あなたのルートパスはあなたが問題を抱えているところだと思います。あなたのコードでは、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を追加することはお勧めしません。これにより、基本的にアプリ全体がファイルを提供できるようになり、ディレクトリ全体にアクセスできるようになります。

私はあなたの例をフォークして更新しました ここ

3
Andy Braham

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>

詳細はこちら

0
Asaf Hananel

私は今日あなたと同じ船に乗っており、デザイナーが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>

幅と高さの属性が期待どおりに機能しないため、私はまだソリューションのスケーリングに取り組んでいます。私が知っているように、入力を拡張することもできます。

お役に立てば幸いです。

0
dcatoday

svgファイルをフォントに変換するには https://icomoon.io/app/#/select 、svgファイルをアップロードして選択し、[フォントの生成]をクリックしてから、[ダウンロード]ボタンをクリックしてダウンロードします。フォントファイルを選択し、フォントフォルダを選択して、プロジェクト内のフォルダに配置します enter image description here

フォントファイルを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'
}

詳細

0