svg要素の基本的な使い方まとめ

Written by defghi1977@xboxLIVE.この文書は全てテキストエディタで作成しています.えーと,そりゃもうゴリゴリと.

14.図形の表示とカーソルイベント

本項では図形の表示に関わる属性と,ポインティングデバイスによるイベントの発生について説明する.htmlよりも事細やかな設定が可能である.

表示に関わる属性

htmlでのcssと同様に要素の表示・非表示に関わる属性が提供されている.display属性及びvisibility属性がこれにあたるが,意味合いとしてはhtmlと同様である.display="none"が要素そのものが(描画上)存在しないものとして扱われるのに対し,visibility="hidden"は描画されないだけで描画領域は確保される.tspan要素においてその違いを確認できるだろう.どちらも似たような効果を持つが,カーソルイベント(click,mouseover,mousemove,mouseout等)の発生可能性に決定的な違いある.display="none"の場合はカーソルイベントが一切発生せず,visibility="hidden"ではpointer-events属性によるイベント発生条件が有効となる.

仕様をよく見るとdisplay属性の値にtable-row等のhtmlでの値が定義されていることに気がつくだろう.これはhtml5等による埋め込みsvgを考慮しているためで,スタンドアロンのsvgファイルにおいてはそれほど意味を持たないが,「none」を打ち消す値として「inline」が規定値として定められている.

htmlの同名のcssプロパティに慣れていると,この属性は図形の表示に関わる要素のみに有効と考えがちだが,svgにおいては直接図形を定義するわけではないlinearGradient要素やfilter要素などにも設定できる.この場合はその要素の持つ機能が無効化されてしまうので,思うような効果が得られない場合は祖先にdisplay:noneが設定された要素が存在しないか確認する必要がある.

display
要素を表示するか.
none
表示しない.この要素を頂点とするノードツリー全体が存在しないものと扱われ,カーソルイベントは発生しない.
inline
表示する.svgにおける初期値.
block,inline-block等の値
表示する.(htmlの親要素にてこれらの値が設定された場合のsvgとしての振る舞いを定めている.)
visibility
要素を表示するか.
hidden
表示しない.カーソルイベントは発生する可能性がある.
visible
表示する
いろはにほへとちりぬるをわかよたれそつねならん いろはにほへとちりぬるをわかよたれそつねならん いろはにほへとちりぬるをわかよたれそつねならん

display属性をインラインsvgで用いる際の注意点

htmlにsvgを挿入する場合,この文書のように複数箇所にグラフィックを挿入するケースはよく有ることだ.すると,文書の構造を分かりやすくするために,それぞれのsvg図形が共通的に用いる要素(例えばlinearGradientやpattern等)を一箇所にまとめたくなる.このような定義情報だけを格納したsvg要素はスクリーンに表示させる必要がないので,画面レイアウトへの影響を避けるために非表示としたいところである.が,ここで不用意にdisplay:noneを指定してしまうと困ったこととなる.実際に試してみよう.

この例ではdisplay="none"で非表示としたsvg要素でグラデーション定義を行い,それを二つ目のsvg要素から参照している.

このようにグラデーションが無効化されていることが判る.linearGradient要素の機能をdisplay="none"が打ち消してしまっているのだ.同様のことを今度はvisibility="hidden"で行なってみよう.

visibility="hidden"では要素の見た目が存在しないだけなので,問題なくグラデーションが表示されている.しかし,本来svgが存在している領域の分レイアウトにすきまが発生してしまう.ではどのようにするのがベストなのだろうか?例えばこのようにsvg図形のサイズを0としてしまう方法がある.

このように意図した通りの動作となった.この他にも位置を画面外に追い出してしまうとか,目に見える要素の背後に隠してしまうとか様々な方法が考えられる.また,svg要素のどれか一つに共通要素を詰め込んでしまうのも一つの手だ.但しこの場合はそのsvg要素が常に表示されていることが条件となる.display属性はhtml要素とsvg要素とを透過的に適用されるので,svg要素を含むdiv要素等にdisplay:noneが設定された場合に同様の問題が発生する.

この動作はインラインsvgがhtmlと同じdomツリー上に展開されることに依る現象であり,svgを使いこなす上での勘所なので是非憶えておこう.

cursor:カーソル定義

cursor要素はカーソルを定義する要素であり,xlink:href属性でカーソルとしたい図形を指定する.一般に画像ファイルをカーソルとすることは可能だが,cursor要素を介することで通常画像の左上が基準となるポインターの位置を調整することが可能となる.現状chromeでのみ動作する.

xlink:href
カーソル画像の参照先url.png画像やsvg画像を参照する.
x,y
カーソルを描画する基準位置.カーソル画像の左上を(0,0)とした際の座標がカーソル位置として解釈される.

cursor要素で定義したカーソルは図形要素のcursor属性から参照する.

cursor
ポインターに対するカーソルを指定.cursor要素の他画像ファイルを直接指定することが出来る.複数指定可能だが,カーソル画像を読み込めなかった場合の代替キーワードを指定しておく必要がある.
autocrosshairdefaultpointermovee-resizene-resizenw-resizen-resizese-resizesw-resizes-resizew-resizetextwaithelp

カーソル画像が有効となる環境は限られているため,クロスブラウザでの動作が求められている場合は使わないほうが良いだろう.

cursor.svgの内容(外部ファイルとして定義)

カーソルの描画位置の調整例を示す.

htmlからcursor要素を参照する

インラインsvgで定義したcursor要素はhtmlから参照することもできるが,現状cursor要素で定義されたカーソル画像の描画位置の調整は無視されるようだ.

pointer-events属性:カーソルイベントの発生条件

svgではpointer-events属性を指定することでポインターイベントを図形のどの部分で発生させるか制御できる.a要素におけるクリック可能判定,マウスイベントの発生条件に影響する.例えばfill=noneの場合,本プロパティを設定しないケースではイベントが発生しないが,pointer-events=all/fillを追加することで塗りつぶされていない領域でもイベントが発生するようになる.またvisibilityの状態によってイベントを発生させるかどうかを指定できる.chromeではイベントを発生させる領域の扱いが若干おかしい.

pointer-events
ポインターに関わるイベント(click,hover,mouseover,mouseout,mousemove)を発生させる条件.
visiblePainted
fill:none,stroke:none以外の部分.(visibility=visibleに限る)
visibleFill
塗りつぶしの部分(visibility=visibleに限る)
visibleStroke
線の部分(visibility=visibleに限る)
visible
図形の描画範囲全体(visibility=visibleに限る)
painted
fill:none,stroke:none以外の部分.
fill
塗りつぶしの部分.
stroke
線の部分.
all
図形の描画範囲全体.
none
どのような状況でも発生しない.つまりイベント上はその要素が存在しないように振る舞う.

例を示す.pointer-eventsの設定により,カーソルをfill領域とstroke領域に乗せた際のhoverスタイルの適用が異なっていることが判る.

fill=noneの例.このように塗りつぶされていなくてもイベントを発生させることができる.

クリックできない クリックできる

pointer-events=noneの使い方として重要なものに,キャプション文字列のイベント発生を回避するというものがある.下を例に取ると,「イベント発生」の部分にカーソルを合わせると,スタイルが変化してしまう.これはrect要素の描画領域が上に重ねられたtext要素によって隠されてしまっているためであり,このままではどこがクリック可能なのか判らず非常に使いにくい.この問題を回避するにはa要素内部にtext要素を挿入する方法もあるが,svgの構成上無理なケースもある.このような場合,text要素にpointer-events=noneを指定することで,描画内容を損なうこと無く下のrect要素にクリックイベントを伝達することが可能となる.

イベント発生 イベント回避