LoginSignup
1
1

More than 3 years have passed since last update.

illustratorでのSVGアイコンを作ってJavaScriptで操作する

Last updated at Posted at 2020-12-25

SVGとは

簡単に言うとブラウザ上でベクター画像描画する形式のことです
ビットマップでないので拡大や高解像度ディスプレイでもぼやけないのが特徴で、曲線的な表現に優れています
また実態はコードなのでcssやJavaScriptで動かすことも可能です
https://developer.mozilla.org/ja/docs/Web/SVG

なんで使おうと思ったの?

弊社のフロー画面ではもともとjQueryとcssストライプでアイコンの色を変えたり配管の表現をしたりしてました
しかし顧客から変更が来るたびに絵を書き直したりスクリプト書き直したりするなどなにかとメンテに手間がかかり変更に弱い
センサー値の表示は結局pタグ書いてposition:absolute;で調整して
何より僕がposition:absolute;が嫌いなのでなんかいい方法ないかなーと思ってたどり着いた方法です

illustratorでSVG画像を作ってみよう

イラレの使い方についてはこちらのyoutubeが一番わかりやすかったですので全くわからない方はまずご覧ください
https://www.youtube.com/playlist?list=PLnDOZwrKSOzamEi7Mc0wVyw3kfrKsvj5g&pbjreload=102

ポンプアイコンを描いてみる

パーツを作成します

まずは必要なパーツを作成します
スクリーンショット 2020-12-25 9.43.48.png

丸と三角を合体

まずはベースとなるパーツを合体させます
パスファインダーの合体を使います
スクリーンショット 2020-12-25 9.46.14.png

テキストをアウトライン化

アウトライン化についてはこちら
要するにテキスト要素をオブジェクトに変換してます
これをしないとほかのパスと合体できないので
スクリーンショット 2020-12-25 9.48.12.png

複合パス化

白丸とPを被せて複合パスにします
スクリーンショット 2020-12-25 9.47.24.png
スクリーンショット 2020-12-25 9.50.32.png

すると白丸部分が消えてPが緑になりました

パスファインダーのナカ窓との違いについて、違いは処理後に一つのパスになるか別々になるかです
アイコンなので一つのパスとしてセットになるのが望ましいので今回は複合パスとしました
あとは白丸をPの背景に据えて完成です

svgとして書き出す

それではsvgとして書き出してみましょう
ファイル>書き出し>書き出し形式...
スクリーンショット 2020-12-25 13.26.53.png

ファイル形式をsvgに指定します
スクリーンショット 2020-12-25 13.27.05.png

そのままOKを押せばsvg形式で書き出されます
スクリーンショット 2020-12-25 13.27.15.png
余談ですが、小数点以下の桁数は書き出しの解像度?らしく、小さいと崩れが起きて大きいと容量が重くなるそうです

ブラウザで見てみる

ブラウザでファイルを開くと作成したアイコンが表示されます
テキストエディタで開くと以下のようになっています
ellipseが背景の白丸、pathが緑の複合パスです

sample.svg
<svg id="レイヤー_1" data-name="レイヤー 1" xmlns="http://www.w3.org/2000/svg" width="262" height="284" viewBox="0 0 262 284">
  <ellipse cx="130" cy="130.5" rx="118.5" ry="117.5" fill="#fff"/>
  <path d="M245.218,256.911,290.5,310H29.5l45.7-53.581a131,131,0,1,1,170.017.492ZM160.5,47a110,110,0,1,0,110,110A110,110,0,0,0,160.5,47ZM120.159,241.469h18.248V172.656c5.056,1.319,10.772,1.539,17.148,1.539,29.679,0,61.118-14.07,61.118-53.423,0-13.191-4.4-47.927-58.48-47.927a212.166,212.166,0,0,0-38.034,3.3ZM138.407,89.333a97.024,97.024,0,0,1,20.006-1.758c22.864,0,40.012,10.552,40.012,34.516S182.376,159.245,156,159.245c-7.036,0-12.972-.439-17.588-1.759Z" transform="translate(-29.5 -26)" fill="#8cc63f"/>
</svg>

ブラウザの検証モードでfill属性を変更すると色を変えることができます

線を描いてみる

線はアウトラインにするか迷うところ

線はアウトラインにするのが常識みたいなんですが、弊社の場合顧客からの要望で変更したりするので編集しやすいように線のままにしとく方が良さげなんですよね
アウトラインにしちゃうと線に戻せないというイラレの都合もあるので
まあ線ぐらい1から書き直しても大した手間じゃないのでいいんですが

line.svg
//線
  <line x1="404" y1="0.961" x2="278" y2="230.961" fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="4"/>
//アウトライン化した線
  <rect x="252.652" y="184.349" width="262.252" height="4" transform="translate(6.448 428.843) rotate(-61.282)"/>

矢印はアウトライン化+合体させる

一方で矢印の場合矢尻と線部分が別パスとして書き出されるので一体化する必要があります

arrow.svg
  <g>
    <line x1="430.68" y1="193.52" x2="316.278" y2="402.349" fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="4"/>
    <path d="M471.778,198.349c-9.154,7.937-22.232,16.842-33.11,20.845l19.99,3.105,13.374,15.173C469.549,226.15,470.014,210.334,471.778,198.349Z" transform="translate(-29.5 -26)"/>
  </g>

その場合アウトライン化して合体です
なので矢印は少々めんどくさいです
矢尻のサイズも調整しないとなので

テキストを描いてみる

テキストはあえてそのままにします

データ量の削減の観点ではテキストパスはアウトライン化させるのが常識のようですが、弊社の場合JavaScriptで書き換えたりする都合上あえてそのままで出力します

text.svg
<text transform="translate(43.87 360.947)" font-size="12" font-family="KozGoPr6N-Regular-83pv-RKSJ-H, Kozuka Gothic Pr6N">山路を登りながら</text>

レイヤーに名前をつけるとidになる

レイヤーに名前をつけてsvg書き出しするとid="名前"となります

スクリーンショット 2020-12-25 14.06.48.png

sample.svg
<svg id="レイヤー_1" data-name="レイヤー 1" xmlns="http://www.w3.org/2000/svg" width="442.532" height="424.77" viewBox="0 0 442.532 424.77">
  <ellipse cx="130" cy="151.961" rx="118.5" ry="117.5" fill="#fff"/>
  <path id="pump" d="M245.218,256.911,290.5,310H29.5l45.7-53.581a131,131,0,1,1,170.017.492ZM160.5,47a110,110,0,1,0,110,110A110,110,0,0,0,160.5,47ZM120.159,241.469h18.248V172.656c5.056,1.319,10.772,1.539,17.148,1.539,29.679,0,61.118-14.07,61.118-53.423,0-13.191-4.4-47.927-58.48-47.927a212.166,212.166,0,0,0-38.034,3.3ZM138.407,89.333a97.024,97.024,0,0,1,20.006-1.758c22.864,0,40.012,10.552,40.012,34.516S182.376,159.245,156,159.245c-7.036,0-12.972-.439-17.588-1.759Z" transform="translate(-29.5 -4.539)" fill="#8cc63f"/>
  <g id="line">
    <line x1="404" y1="0.961" x2="278" y2="230.961" fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="4"/>
  </g>
  <rect id="outline" x="252.652" y="184.349" width="262.252" height="4" transform="translate(6.448 428.843) rotate(-61.282)"/>
  <g id="arrow">
    <g>
      <line x1="430.68" y1="214.981" x2="316.278" y2="423.81" fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="4"/>
      <path d="M471.778,198.349c-9.154,7.937-22.232,16.842-33.11,20.845l19.99,3.105,13.374,15.173C469.549,226.15,470.014,210.334,471.778,198.349Z" transform="translate(-29.5 -4.539)"/>
    </g>
  </g>
  <text id="text" transform="translate(43.87 360.947)" font-size="12" font-family="KozGoPr6N-Regular-83pv-RKSJ-H, Kozuka Gothic Pr6N">山路を登りながら</text>
</svg>

なのでid="pump_"や"pump_1-name"みたいに命名規則を作って、あとはプログラムで"-"でsliceしてゴニョゴニョっとできそうな気配
うまいことプログラム組めばイラレで絵書いてid決めてsvg書き出すだけでペコペコ動くみたいなこともできそう

JavaScriptで操作する

簡単にJavaScriptで動かしてみましょう

jQueryセレクタでは取得できない

注意として、どうやら$('#pump')とかでは取得できないようです
なので以下のようにします

html
<object id="svg" data="sample.svg" type="image/svg+xml"></object>
JavaScript
$(function(){
  let svg = document.getElementById('svg').objectContent;
  let pump = $(getElementById('pump'));
});

ポンプの色を変える

pathの色はfillという属性を変更すると変えられます

JavaScript
pump.css('fill', '#ff0000'); //赤に変わります

線の色を変える

line要素の場合はstrokeという属性です
一方アウトライン化しているとpath要素になるのでfillで変化させます

JavaScript
line.css('stroke', '#ff0000'); //line要素
outline.css('fill', '#ff0000'); //アウトラインの場合

矢印を点線、実線切替する

display: none/block;で表示非表示

JavaScript
switch (flag) {
        case 0:
            arrow.css('display', 'none');
            arrow.hide();
            break;

        case 1:
            arrow.css('display', 'block');
            arrow.hide();
            break;

        default:
            break;
    }

テキストを書き換える

jQueryのtext()が使えます

JavaScript
text.text('変更する');

マウスオーバーで機器名表示

jQueryのhover()が使えます

JavaScript
$(img).hover(
        function (e) {
            $(name).show();
        },
        function (e) {
            $(name).hide();
        }
    );

まとめ

とまぁゴリゴリやれば作れるのだけれどもまだまだ改良の予知あるなと思ったところです
少なくとも複数色のアイコンを作成してとかの手間は減ってテキストの表示位置もプログラマのセンスに依存するようなこともなくなるのでいいかなと思うのですがね
理想は絵を描いて命名規則に通りにレイヤーに名前つけて出力すれば動く、もしくはこの機器はこのアイコンをこの位置に表示みたいな設定したら配置されて動くみたいなぐらいまで工数削減実現したら素敵ですね
個人的推しなvue.jsとかモダンJavaScriptフレームワークでwebソケットつないでインタラクティブにしたいななんて思いながら

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1