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 に変換した際に図形の輪郭となる。
ベクターツールにおいて、繋がったアンカーポイントの連続は「線」と呼ばれる。線の始点と終点を結んだ領域は「塗り」と呼ばれる。それを SVG に変換すると「塗り」はfill
、「線」はstroke
となる。
可視性
SVG はvisibility
プロパティーで可視か不可視かを指定できる。CSS と同じく、visible
かhidden
を値に持つ。visibility = visible
の時は SVG は可視で、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 怖くなってきた。