SVG pointer-events 2017
- 公開日
- タグ
- Advent Calendar
- CSS
- SVG
SVG Advent Calendar 2017の 20 日目。
pointer-events: none
については過去に書いたとおり、なかなかどうして、好きすぎて困っている。
また、pointer-events
プロパティーが大好きなみなさんなら、これが SVG 由来のものだというのは当然ご存知だろう。HTML の要素に指定が有効な値は実質 auto
と none
だけだが、SVG の要素についてはその限りではない。MDN を見ると以下の値がある。
- auto
- none
- fill
- stroke
- all
- painted
- visibile
- visibleFill
- visibleStroke
- visiblePainted
これらの値によってポインターイベントのターゲットにどのように変化するのか、ひとまず pointer-events
プロパティーに関わる SVG の特徴を理解する必要がある。
塗りと線
SVG の図形は概ねベクターツールのそれと同じで、座標・次の座標へつながるときの向き・向きの強さで表せる。
繋がれた座標の連続は「線」と呼ばれる。線の始点と終点を結んだ領域は「塗り」と呼ばれる。それを SVG に変換すると「塗り」は fill
、「線」は stroke
となる。
可視性
SVG は visibility
プロパティーで可視か不可視かを指定できる。CSS と同じく visible
か hidden
を値に持つ。visibility = visible
の時は可視、visibility = hidden
の時は不可視となる。
塗りと線に指定できる値
概ねCSS の<color>型と同じ。厳密には<paint>型なのだが、実質的に<color>型という解釈でいいと思う。
https://www.w3.org/2011/07/29-svg-minutes.html#item02 https://triple-underscore.github.io/SVG11/types.html#DataTypeColor
SVG の装飾方法
SVG にスタイルを当てる方法はだいたい3つある。フィルターやマスクなど考えるとその限りではないが、まぁだいたい3つでいいと思う。
<!-- style属性での指定 -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="30" style="fill: gold; stroke: black; stroke-width: 2" />
</svg>
<!-- style要素での指定 -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<style>
circle {
fill: gold;
stroke: black;
stroke-width: 2
}
</style>
<circle cx="50" cy="50" r="30" />
</svg>
<!-- プレゼンテーション属性での指定 -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="30" fill="gold" stroke="black" stroke-width="2" />
</svg>
(大まかに言って)このいずれかの装飾で、可視性/塗り/線を設定する。
早見表
そして pointer-events
プロパティーと可視性/塗り/線の関係は次の通りとなる。
pointer-events 値\依存する項目 | visibility 値 | fill 値 | stroke 値 | 簡単な解説 |
---|---|---|---|---|
auto | visible |
none 以外 |
none 以外 |
visiblePainted と同じ |
none | -- | -- | -- | 何もターゲットにならない |
fill | -- | -- | -- | 塗り部分がターゲット |
stroke | -- | -- | -- | 線部分がターゲット |
all | -- | -- | -- | 塗りと線がターゲットになる |
painted | -- | none 以外 |
none 以外 |
値が none 以外なら塗りも線もターゲット |
visible | visible |
-- | -- | 可視であれば none 値でも塗りと線がターゲットになる |
visibleFill | visible |
-- | -- | 可視であれば none 値でも塗りがターゲット |
visibleStroke | visible |
-- | -- | 可視であれば none 値でも線がターゲット |
visiblePainted | visible |
none 以外 |
none 以外 |
可視でかつ none 値以外の塗りと線がターゲット |
pointer-events
に指定できる値は他に inherit
があるが、これはただの継承なので表には含めない。
だいたいは fill
や stroke
の値には左右されないが、 painted
/ visiblePainted
のときは none
以外でないといけなくなることがわかる。
none と transparent と opacity と visibility
visibility:hidden
以外でも「見えない」指定は可能だ。色指定なしの none
、透明色指定の transparent
、全透過の opacity: 0
がある。
しかし仕様によれば transparent
と opacity
も pointer-events
プロパティーの挙動には影響を与えない。影響を与えるのは「色指定あるなし」と「可視性あるなし」のみということだ。
実食
仕様をあれこれ説明してもしっくりこないと思うのでさっさと触っていこうと思う。SVG で fill と stroke が色付きと none
の 4 パターンの path 要素を用意し、プルダウンで pointer-events
、visibility
、opacity
を切り替えられるサンプルを作った。path 要素あたりをクリックし、イベントが制限されていなければ黄色いエリアに「Clicked!」と文字が出る(その後消える)。
実装ロジックとしては、プルダウンを選択するとそれぞれのプレゼンテーション属性値が各 SVG へ書き込まれる仕組みになっている。
触ってみると気づくことがある。「fill = none
のみ」とか「stroke = none
のみ」をターゲットにした pointer-events
の制御ができない。これは仕様にないので仕方がない。しかし次の 3 点は仕様と違っておかしい。
stroke
でも fill=none な SVG をクリックでイベントが発火するfill
でも stroke=none な SVG をクリックでイベントが発火するpainted
でも fill と stroke もnone
な SVG でクリックイベントが発火する
仕様とはいったい? 特に3つ目は不思議な動きをする。これに visibility = hidden
してみると、期待通り fill = none / stroke = none
な SVG はクリックが発火しなくなるのだ。painted
は visibility
の値で挙動が変わらないはず。手元の Google Chrome 63、Safari 11.0、Firefox 57.0.1 で確認したがいずれも同じだった。
他の値の組み合わせはどうやら仕様通りに実装されていそうだった。全部のブラウザでは見ていないので何か差があるかもしれない。
誰か知っていることがあったら教えて欲しい。
SVG 怖くなってきた。