Help us understand the problem. What is going on with this article?

Ionicでカスタムアイコンを使う

More than 1 year has passed since last update.

Ionic Advent Calendar 2019
4日目の記事です。

Ionicon にちょうどいいアイコンが見つからない、そんなときにカスタムアイコンを使用する方法です。
日本語の記事がなかったので。

参考にしたサイト(というかIssue)
https://github.com/ionic-team/ionicons/issues/589

1. アイコンに使用するSVG画像を用意する

アイコンにはSVG画像を使用します。
SVG画像は、JPGやPNGといったドットで描くラスター画像と異なり、線(path)で描画するベクター画像です。拡大縮小に強く、大きくしてもジャギったりしません。そして軽量。

Illustratorの他、InkscapeなどのフリーソフトでSVG画像を自作してもよいですが、フリーで使えるアイコンがダウンロードできるサイトもたくさんあります。
今回はこちらからこのSVGファイルをダウンロードして使用することにします。
SnapCrab_NoName_2019-11-6_23-38-58_No-00.png
ちなみに Ionicon のページ でもアイコンのSVGファイルはダウンロードできます。
SnapCrab_NoName_2019-11-6_21-13-25_No-00.png

2. assetsにフォルダを追加して配置

プロジェクトの assets フォルダ内にフォルダを追加して、ダウンロードしたSVGファイルを置きます。(ファイル名はダウンロード時から変更してあります)
SnapCrab_NoName_2019-11-6_23-41-38_No-00.png

3. ion-icon タグで使う

ion-icon タグの src 属性に先ほど配置したファイルを指定するとアイコンとして利用することができます。
SnapCrab_NoName_2019-11-6_23-44-18_No-00.png
SnapCrab_NoName_2019-11-6_23-44-35_No-00.png

4. うまく表示できないんだけど?

アイコンによってはうまく表示できない場合があります。
例)
SnapCrab_NoName_2019-11-6_23-58-27_No-00.png
普通のボタンとクリアボタンで色が変わっていません。
ion-icon タグで使用して自動的にスタイルを変更してくれるのは、path のみで構成されたSVGファイルだけです。塗りつぶし(fill) や縁取り(stroke)が使用されたSVGファイルではうまく表示できません。
ちなみにこの葉っぱのSVGファイルはこんな感じ。fill や stroke が使われています。
SnapCrab_NoName_2019-11-7_0-3-36_No-00.png
うまく表示できるSVGファイルはこんな感じ。path だけで構成されています。(IoniconのページでダウンロードできるSVGファイルも同様です)
SnapCrab_NoName_2019-11-7_0-6-45_No-00.png
うまく表示できなかったファイルから fill や stroke を除いて、いい感じになることもあります。編集可のフリー素材だったら試してみてもいいかもしれません。

ちなみに葉っぱアイコンは path だけにしてみましたがイマイチでした。
SnapCrab_NoName_2019-11-7_0-12-59_No-00.png
SnapCrab_NoName_2019-11-7_0-13-7_No-00.png
Illustratorなどで自作のアイコンを作る場合、自動で色が変更されるようにしたければ path だけで作成するようにしましょう。

5. name属性で使いたい

ion-button に使えてめでたしめでたし、かと思いきや、このままでは困ったことがあります。ActionSheet などのボタンに使いたい場合です。
ActionSheet などボタンを配置できるコンポーネントの場合、ボタンにアイコンを表示する際 icon フィールドにアイコンの名前を設定します。
SnapCrab_NoName_2019-11-7_23-20-44_No-00.png
SnapCrab_NoName_2019-11-7_23-22-31_No-00.png
追加したカスタムアイコンは src 属性にパスを渡すことで表示することができましたが、ActionSheet の buttons には src 属性がないため、ファイルパスを渡すことはできません。
そこで今度は、カスタムアイコンに名前をつけて、Ionicon と同様に name を指定して使用できるようにします。

6. name で指定できるようにする

今回追加したカスタムアイコンを name="translate" で使用できるようにします。name は標準の Ionicon と被らないようにしましょう。

まず assets/custom-icon に配置したSVGファイルをコピー&ペーストして複製します。
そしてそれぞれ、以下のようにファイル名を変更します。
SnapCrab_NoName_2019-11-7_23-28-50_No-00.png
使用したい name の頭に ios-md- をつけました。
察しのいい方はお気づきかもしれませんが、 ios- がついている方のファイルが iOS 端末で、 md- がついている方のファイルが Android およびデスクトップ端末で表示されます。
今回はどちらも同じ画像ですが、iOS と Android/PC で異なる画像を表示したい場合は、iOS 用の画像を ios-xxxx.svg 、Android/PC 用の画像を md-xxxx.svg という名前にします。

次に Angular のビルド設定を変更します。
angular.json の projects/app/architect/build/options/assets に以下の記述を追加します。

{
  "glob": "**/*.svg",
  "input": "src/assets/custom-icon",
  "output": "./svg"
}

SnapCrab_NoName_2019-11-7_23-36-55_No-00.png

これで準備が整いました。
ion-icon に src 属性でファイルパスを指定していた部分を name="translate" に変更してみましょう。
SnapCrab_NoName_2019-11-7_23-38-56_No-00.png
SnapCrab_NoName_2019-11-7_23-39-19_No-00.png
ちゃんと表示できていますね。
ActionSheet でも icon: 'translate' を指定してみましょう。
SnapCrab_NoName_2019-11-7_23-40-36_No-00.png
SnapCrab_NoName_2019-11-7_23-41-11_No-00.png
やったぜ。

7. 特別な名前 logo-

これでカスタムアイコンに好きな名前をつけて Ionicon と同じように使えるようになったわけですが、logo- で始まる名前を付ける場合は注意が必要です。
前述の通り iOS では ios- で始まるファイル、Android/PC では md- で始まるファイルを取得しにいきます。

(Chrome Dev Tools の Networkログ)
iOS の場合
SnapCrab_NoName_2019-11-7_23-51-49_No-00.png
Android/PC の場合
SnapCrab_NoName_2019-11-7_23-52-1_No-00.png

ではカスタムアイコンの名前を translate から logo-translate にしてみましょう。ファイル名も以下のように変更します。
SnapCrab_NoName_2019-11-7_23-54-11_No-00.png
SnapCrab_NoName_2019-11-7_23-54-38_No-00.png
SnapCrab_NoName_2019-11-7_23-55-7_No-00.png
アイコンが表示されなくなってしまいました。
コンソールにはエラーが出力されています。
SnapCrab_NoName_2019-11-7_23-55-42_No-00.png
ネットワークログを見ると、どうやら logo-translate.svg というファイルを取得しにいっているようです。(そして404エラーで失敗している)
SnapCrab_NoName_2019-11-7_23-56-20_No-00.png
logo- は特別な名前で、iOS と Android/PC で表示するファイルを 変えません 。どちらの場合も logo-translate.svg を取得して表示します。
逆に言うと、iOS と Android/PC で表示するアイコンを変えない場合は、ファイルを2つ用意する必要はなく logo-xxxx.svg を1つ用意すればよいわけです。
その代わりアイコンの名前は必ず logo-xxxx となります。頭の logo- は固定です。
ファイル名を以下のように修正すればアイコンは表示されます。(そしてファイルは1つでよくなった)
SnapCrab_NoName_2019-11-8_0-4-56_No-00.png
SnapCrab_NoName_2019-11-8_0-5-15_No-00.png

8. 余談(1)

アイコンを名前で指定できるように angular.json に記述を追加しましたが、追加した記述のすぐ上を見てみると、指定しているディレクトリパスが違うだけで他は全く同じです。
SnapCrab_NoName_2019-11-8_0-8-1_No-00.png
上の記述は Ionic が Ionicon を使うための記述です。上の記述にあるディレクトリパスを見てみましょう。
SnapCrab_NoName_2019-11-8_0-9-45_No-00.png
ずらりとSVGファイルが並んでいます。そして(画像にはありませんが)ファイル名は ios- logo- md- で始まっています。

今回、 Ionic と同じ方法でカスタムアイコンを追加したのです。そのお陰で name を指定してアイコンを表示することができました。

9. 余談(2)

ion-icon タグは割と柔軟に CSS を適用することができます。
CSS を当てると、 ion-button タグ以外でも使いやすいアイコンになるのでオススメです。
SnapCrab_NoName_2019-11-8_0-45-12_No-00.png
SnapCrab_NoName_2019-11-8_0-23-40_No-00.png
SnapCrab_NoName_2019-11-8_0-30-48_No-00.png

アイコンの塗りつぶし色を fill で指定しているのがポイントです。
fill はSVGファイル内部に記述される属性でしたが(そして今回アイコンとして使うには存在が邪魔でしたが)、CSSで指定することができます。

10. 終わりに

カスタムアイコンを使用できるようになると、アプリのデザインの幅がぐんと広がります。
またカスタムアイコンを Ionicon と同じように使えるのもとても便利です。
私も冒頭の Issue を見つけるまでは、ActionSheet に cssClass を指定してグローバルCSS で ::before疑似要素をつっこんで画像表示、ああでも Android ではグレーだけど iOSでは primary color で表示されるからファイルを2つ用意してクラスも2つ記述して...という労力を費やしていました。

フリーのアイコンを使用する際は、許諾や利用条件、変更の可否などを調べて、著作権を侵さないよう注意しましょう。

gekijin
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away