SVG学習 12日目「defsとuseでインスタンス表示」

2019年1月9日

SVG テクノロジー プログラミング 特集

t f B! P L
SVGって、めちゃくちゃ便利なのに、いまだにcanvas使っているサービスみると、非常にもどかしくなる。 ブラックボックス化するにはcanvasがいいのかもしれないが、DOM構造を操作できる利点でSVGが使い勝手が非常にいい。 尚且つ、ビットマップでないという事で、画像がどんなに大きくなっても、一定のデータ容量で済むというのが最高の利点ではないでしょうか? そして、なんとインスタンス機能なんか使おうもんなら、「どんだけ容量軽くできんねん!!!」てな具合に、ネットコンテンツとしては最適化できてしまうわけです。 今回は、そんなSVGのインスタンス機能を搭載するべく「defs」と「use」タグを覚えてみました。

画像解説

まずはじめに、今回扱う画像(SVG)の内容を説明しておきます。 <svg version="1.1" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg"> <style type="text/css">*{fill:black;} .stroke{fill:none;stroke:black;}</style> <path d="M 20 20 v 450 h 450 v -30 h -420 v -420 z" /> <g transform="translate(80,160)"> <path d="m 20 60 h -20 v 120 h 20 v 60 h 20 v -60 h 20 v -120 h -20 v -60 h -20 v 80 h 20 v 80 h -20 v -80 h 20 z" /> </g> <g transform="translate(180,110)"> <path d="m 20 0 v 60 h -20 v 120 h 20 v 60 h 20 v -60 h 20 v -120 h -20 v -60 z" /> </g> <g transform="translate(280,60)"> <path d="m 15 60 h -15 v 120 h 15 v 60 h 30 v -60 h 15 v -120 h -15 v -60 h -30 v 80 h 25 v 80 h -25 v -80 h 20 z" /> </g> <g transform="translate(380, 10)"> <path d="m 20 0 v 60 h -20 v 120 h 20 v 60 h 20 v -60 h 20 v -120 h -20 v -60 z" /> </g> </svg> インラインSVGとして使ってもいいですが、上記コードをファイルに保存しておくと、imgタグなどで扱えて便利です。 株価チャートを表すアイコンですが、シンプルにpathのみで輪郭を書いてfillで塗りつぶしています。 中のグラフ箇所が似たような画像を4つ並べているのですが、これをインスタンス化すれば、もっとシンプルなコードになるはずです。

インスタンス化して解説

<svg version="1.1" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink"> <style type="text/css">*{fill:blue;} .stroke{fill:none;stroke:blue;}</style> <defs> <symbol id="stock1"> <path d="m 20 60 h -20 v 120 h 20 v 60 h 20 v -60 h 20 v -120 h -20 v -60 h -20 v 80 h 20 v 80 h -20 v -80 h 20 z" /> </symbol> <symbol id="stock2"> <path d="m 20 0 v 60 h -20 v 120 h 20 v 60 h 20 v -60 h 20 v -120 h -20 v -60 z" /> </symbol> </defs> <path d="M 20 20 v 450 h 450 v -30 h -420 v -420 z" /> <use transform="translate(80,160)" xl:href="#stock1" /> <use transform="translate(180,110)" xl:href="#stock2" /> <use transform="translate(280,60)" xl:href="#stock1" /> <use transform="translate(380,10)" xl:href="#stock2" /> </svg> 色が変わっただけではなく、中のデータ総容量が少なくなっている点に注目してください。 上記で記述している"g-path"のDOM構造をdefsでセットしたインスタンスをuseで呼び出しているというシンプルな構造にしています。 4種類のうち、2パターンをインスタンス化しているので、さほど大きな削減に見えないかもしれませんんが、より複雑になってくると、このインスタンス処理で非常に軽くて複雑で素敵な画像を作ることが可能になります。 色々なサイトでdefsの解説をしてくれていたんですが、ブラウザのバージョンのせいかわからないが、表示できなかったので、この機能を使う注意点を解説しておきます。

defs-useの使用注意点

svgタグにxlink属性をセットする。 <svg version="1.1" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink"> この箇所ですね。 xmlns:xl="http://www.w3.org/1999/xlink" と記述して、 useタグのhref属性で、xl:href="#id名" とすることで、参照が可能になります。 他のサイトで、"href:xlink"と書かれていて、かなりハマってしまったので、騙されないようにしましょう!。 サンプルに書かれている"symbol"タグは、複数のシンボルを作るときに、defs内に記述するgタグのような扱いだと思ってください。 そして、必ずしもsymbolタグを使わなくてもちゃんとインスタンス化できるので、次はもっと使いやすくしてみます。

symbol以外のインスタンス設定

<svg version="1.1" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink"> <style type="text/css">*{fill:red;} .stroke{fill:none;stroke:red;}</style> <defs> <path id="stock1" d="m 20 60 h -20 v 120 h 20 v 60 h 20 v -60 h 20 v -120 h -20 v -60 h -20 v 80 h 20 v 80 h -20 v -80 h 20 z" /> <path id="stock2" d="m 20 0 v 60 h -20 v 120 h 20 v 60 h 20 v -60 h 20 v -120 h -20 v -60 z" /> </defs> <path d="M 20 20 v 450 h 450 v -30 h -420 v -420 z" /> <use transform="translate(80,160)" xl:href="#stock1" /> <use transform="translate(180,110)" xl:href="#stock2" /> <use transform="translate(280,60)" xl:href="#stock1" /> <use transform="translate(380,10)" xl:href="#stock2" /> </svg> わかりやすく赤色にしてみましたが、色については全く意味がないので、単なる区分けのためと考えてください。 そして、symbolタグを、もっとストレートにpathタグに直接idを貼り付けてみました。 さらに若干ですが、シンプルになっているのがわかると思います。 そして、useタグは、gタグに記述するように、transformなどでコントロールすると、かなり便利に操作できますよ。

defsを使わなくてもインスタンスは使える

最後に、defsを使わなかったらどうなるでしょうか? 答えは、問題なく機能します。 ただし、defsは、画面表示をしないタグなので、事前準備するタグだと考えてください。 より効率的に使いたければ、一番最初に表示するタグにidを付ける事で、さらにコードを軽減することが可能になります。 <svg version="1.1" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink"> <style type="text/css">*{fill:green;} .stroke{fill:none;stroke:green;}</style> <path d="M 20 20 v 450 h 450 v -30 h -420 v -420 z" /> <g transform="translate(80,160)"> <path id="stock1" d="m 20 60 h -20 v 120 h 20 v 60 h 20 v -60 h 20 v -120 h -20 v -60 h -20 v 80 h 20 v 80 h -20 v -80 h 20 z" /> </g> <g transform="translate(180,110)" xl:href="#stock2" > <path id="stock2" d="m 20 0 v 60 h -20 v 120 h 20 v 60 h 20 v -60 h 20 v -120 h -20 v -60 z" /> </g> <use transform="translate(280,60)" xl:href="#stock1" /> <use transform="translate(380,10)" xl:href="#stock2" /> </svg> いかがでしょうか? もはやsvgって怖くなくなりましたよね? むしろ無限の可能性が詰まっていて、ワクワクしますね。

人気の投稿

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。

ブログ アーカイブ