ほんのちょっと高度なSVGスプライトの使い方:2

4871 0

前回のほんのちょっと高度なSVGスプライトの使い方続きです。
今回の話は一回で済まそうと思っていたのですが

  1. 単色アートワークと多色アートワークで必要な知識が変わってくる
  2. 1ゆえにSVG各要素の仕様に対する理解が必要
  3. 加えてSVG要素へのスタイル適用に関する理解が必要

という点から、一つにまとめると非常に長くかつ複雑になってしまうため、
2回に分け、今回は単純なアートワークでsymbol要素とg要素でのuse要素参照時の挙動の違いと、svg要素下のuse要素の振る舞いの理解(=SVGの仕様に対する理解)を深めるをテーマに書かせていただきます。
今回お話するポイントをしっかり理解することで、次回の内容が非常にスムーズに分かり、グラフィックのモジュール化用のSVGのみならず、今後SVGを使用する際に様々な応用ができるようになると思います。

では実際にロゴを縦型・横型(シンボル、ロゴタイプのみ)の4タイプに使用できる スプライトファイルを作成していきましょう。 こちらができると、このように1つのファイルから複数の形状へ展開できるスプライトデータになります。

svg-usage_2_00

今回の内容は「共通部分を持つ複数パターンのアートワークを1つのファイルで作成する」と言い換えられます。

ちょっと注意点がいくつかあるので、新しくスプライトデータを作ります。

1.グラフィックモジュール用スプライトデータを作成する

svg-usage_2_01

まずはこのように別々になっているアートワークを 共通部分が(きっちりズレなく)重なるようにします。

svg-usage_2_02

そして、共通部分の片方だけを残すように削除。

次に「レイヤーの分け方」。
ここは後でテキストエディタ等で修正しても良いのですが、Illustrator上のほうが 若干やりやすいかなと思うので、このまま続けます。 (テキストエディタで行う場合、SVGの構造をしっかり理解していないと結構混乱するかもしれません。)

現在は

  • 「縦型」
  • 「横型」

と2つのレイヤーに分かれていますが、これを下記のような形状になるように

svg-usage_2_00
  • 「symbol」…シンボルのみ
  • 「vertical」…縦型のロゴタイプのみ
  • 「horizontal」…横型のロゴタイプのみ

の3つのレイヤーに分けます。

svg-usage_2_03

ここまでできたら書き出しましょう。

svg-usage_2_04

サブセット等は「SVGをつくってみよう![初級編]」などを参考にしていただければよいかと。
直線が多い場合は1桁
曲線が多い場合は5桁くらいまで上げてもいいと思います。

2.ブラウザチェック

書き出しが終わったらブラウザへドラッグ&ドロップして確認しましょう。
まだ、SVGスプライト化していないのでこのように重なって見えるはずです。

svg-usage_2_05

レイヤー分けが上手くいっていれば画像のように svg要素の中にg要素が3つ指定したidで出力されているはずです。

同時に、それぞれのg要素がちゃんと想定通りになっているかもチェック。

svg-usage_2_06 svg-usage_2_07 svg-usage_2_08

ここまでは恐らく難なくいけるはずです。 そして、ここからが本題。
今回作成したデータをスプライトデータにします。

3.スプライトデータに編集

svg-usage_2_09

まずは細かなことは置いておいて、手順の説明を先にさせていただきます。
いつも通り、

  • 不要な改行とインデント等を削除
  • 不要なg要素と消し忘れ等で残った不要な要素を削除
  • style属性を削除(※どうしても必要なものを除いて)
  • グラフィックをdsfs要素でwrap

ここまで行うと、スプライトデータの構造としては、このようになるでしょう。

<svg class="defs" viewBox="0 0 403 53">
	<defs>
		<g id="horizontal">
			<path d="...">
			<path d="...">
				.
				.
		</g>
		<g id="vertical">
			<path d="...">
				.
				.
		</g>
		<g id="symbol">
			<path d="...">
				.
				.
		</g>
	</defs>
</svg>

そして、ここからがいつもと違うところです。
今回はこの状態のスプライトデータのg要素を直接参照させます
また、参照時には下記のようにsvg要素下にuse要素を複数配置します

<svg class="use1" viewBox="....">/*g要素からの参照なのでviewBox属性は必須!*/
	<use xlink:href="#symbol" />
	<use xlink:href="#vertical" />
</svg>

「バラしたグラフィック要素を使用時、用途毎に組み立てる」といったイメージで考えていただけると分かりやすいかと思います。

4.スプライトデータからグラフィックを組み立てる

svg-usage_2_00

では実際に、こちらの画像のように、このデータ1つから4タイプに使用してみましょう。

  • 「縦型」は#symbolと#verticalの組み合わせ
  • 「横型」は#symbolと#horizontalの組み合わせ
  • 「シンボルのみ」は#symbol
  • 「ロゴタイプのみ」は#horizontal

なので、記述はこのようにしてやるとよいでしょう。(※画像ではuse要素にidやclassが付与されていますが、今は無視してOKです)

<!-- 縦型として使用 -->
<svg class="vertical" viewBox="0 0 42 53">
	<use xlink:href="#symbol" />
	<use xlink:href="#vertical" />
</svg>
<!-- 横型として使用 -->
<svg class="horizontal" viewBox="0 0 403 53">
	<use xlink:href="#symbol" />
	<use xlink:href="#horizontal" />
</svg>
<!-- シンボルのみで使用 -->
<svg class="symbol" viewBox="0 0 42 42">
	<use xlink:href="#symbol" />
</svg>
<!-- ロゴタイプのみで使用 -->
<svg class="logotype" viewBox="40 0 403 53">
	<use xlink:href="#horizontal" />
</svg>

使用時の各svg要素のviewBox指定は

縦型(.vertical) #symbolのwidth分とスプライトデータのviewBoxのheight分
横型(.horizontal) スプライトデータのviewBoxと同じでもOK(拘るなら、#verticalの高さ分をviewBoxのheightから引くとよい)
シンボルのみ(.symbol) #symbolの大きさ分のviewBox
ロゴタイプのみ(.logotype) #horizontalの大きさ分のviewBox

と指定してやると意図した通りに表示されます。
ここで前回やった内容が活きてきますね!

グラフィックモジュール用のSVGスプライトデータを作成、使用するにはviewBox指定に対する理解が必須になります
しかしそれが分かっていれば、特に難しいことは何もなく、むしろ「え?これだけのこと??」と思うかもしれません。笑

5.use要素の仕様を理解しよう

さて、では今回の裏テーマとでも言うべき題材に入りましょう。
次回に繋がる部分でもあり、今後様々な用途でSVGスプライトを使用していくにあたり、理解しておいたほうが良い「仕様」に関するお話です。

今回のポイントでもあった箇所ですが「なぜsymbol要素ではなく、g要素で作成するのか?」といった疑問を持たれた方も少なくないのではないでしょうか?
実際、symbol要素でもこうしたスプライトデータの作成は可能です。しかし、SVG関連の各要素の仕様を理解していないとまったく意図した通りのグラフィックが生成されないかったり、手順が増えたり等少々面倒なことがあります。

SVGスプライトを使用する際、必ずuse要素を使用しますね?
このuse要素は他のhtml要素などと比べてもちょっとユニークな仕様があります。そのあたりをポイントを絞ってお話していきます。

Point1:use要素はsymbol要素から参照したのかg要素から参照したのかで、振る舞いの違いがあります。

これまでSVGスプライトのつくり方を説明させていただいた際はすべて「symbol要素で」と言っていたかと思います。 しかし、今回のような「グラフィックのモジュール化用SVGスプライトデータ」は、下記のようにsvg要素以下に複数のuse要素を持たせて一つのsvg要素を構成します。

<svg class="use1" viewBox="....">/*g要素からの参照なのでviewBox属性は必須!*/
	<use xlink:href="#foo" />
	<use xlink:href="#bar" />
</svg>

svg要素下にuse要素を一つしか持たせない場合では、親となるsvg要素へスタイルを付与すれば何も問題はありませんが、このように複数のuse要素を持たせた場合では「何の要素から参照したのか」の振る舞いの違いによって意図した通りの形状にならないケースが生まれます。

use 要素が symbol 要素を参照している場合

参照先の symbol とその内容は、根元の symbol が svg に置き換えられることを除いて,生成される木に末端まで複製される。 この生成された svg は常に明示的に width 属性と height 属性の値を持ち, use 要素の width と height の値が移植されるが、これらが use 要素に与えられていないものについては値 ‘100%’ をとる。

文書構造-SVG1.1 use要素

つまるところ、symbol要素をuseで参照すると、(親となるsvg要素に対して)widthは100%になりますよ ということです。

svg-usage_2_10

こちらはこの記事の最初の画像(g要素から参照したもの:左)とsymbol要素から参照したもの(画像右)を並べたものです。
※他のhtmlの記述内容やスタイル指定ももちろん同じにしてあります。

ご覧の通り、右側のsymbol要素からの参照では#symbolと#horizontalが重なってしまったり、#symbolのサイズがすべて同じになったりしていますね?
この振る舞いの違いがある為、g要素での参照をおすすめします。

Point2:use要素はcssでのwidth,height指定を受け付けない

使用時のサイズがバラけてしまったので調整するために個々にサイズを変えたい…という場合、width属性やheight属性をuse要素に付与する必要があります。(これが手間になる)
※一応、その他のプロパティはほぼ全て受け付けるのでtransform:scaleなどで対応するのも無しではないですが…

widthやheightはviewBoxを見ればだいたい分かるので、そのまま記述すれば良いですが、はっきり言って使用する毎にそんなことをするのは面倒くさい。
なので、g要素から参照するほうが楽です。

また、同様の理由から
スプライトデータ作成の段階で、全アートワークの大きさがきっちり揃っているように作成しておかなければ 使用時に微妙なサイズのズレが生まれますのでご注意ください。
この微妙なズレを都度cssやwidth,height属性等で調整するのは至難の技です。必ず、作成時の段階でサイズを揃えるよう調整しておきましょう

Point3:use要素は内包要素を持っていない(※10/18追記有り)

ここに関しては次回の内容に大きく関わってくる箇所でもあるので、次回詳しくお話ししますが、少し今回も触れておきます。
スプライトデータ内のg要素にはpath要素などが入っています。しかし、useで参照した際、それらの要素はDOMツリー上には複製されません(※ちょっと語弊がありますが)。

なので

<svg viewBox="0 0 42 53">
    <use class="symbol" xlink:href="#symbol" />
    <use class="vertical" xlink:href="#vertical" />
</svg>
.symbol path{fill:#aaa}
.vertical path{fill:#333}

といった指定をしても、「存在しない要素への指定」になるため、このスタイルが適用されることはありません。
svgスプライトからの参照で使用したsvg要素に対してスタイル指定できるのは、親となるsvg要素とuse要素に対してのみ有効となります

まとめ

  • スプライトデータをg要素で作成する
  • 使用時のsvg要素下にuse要素を複数持たせて「組み立てる」
  • viewBoxの指定方法を知っていることは大切!
  • use要素はcssのwidth,height指定を受け付けない
  • 必ず、作成時の段階でサイズを揃えるよう調整しておく

仕様に関する箇所は、そんなに難しく考えなくてもよいところでもありますが、知っているのといないのでは今後違いが出てくるかなということでお話しさせていただきました。

若干小難しく書きすぎた感が否めないのですが…もし、「意味分からん!」などありましたらお申し付けいただけると幸いです。。(文章あまり上手じゃないです…)

では、次回は『多色使いのアートワークによるグラフィックモジュール用svgスプライトの作成方法』をお話しさせていただきます!

svg-usage_3_00

ここまでできれば、恐らく普通に使う分にはsvgスプライトをほぼ思い通りに扱えるのではないかなと思います。お楽しみに!

…多分、次回はもう少し早めに更新できるのではないかな…?と思いますが…なるべく間が空かないよう頑張ります。。

SVGスプライト

Comments

Comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

認証コード * Time limit is exhausted. Please reload CAPTCHA.