ポインタイベントプロパティとのSVG相互作用の管理
公開: 2022-03-10pointer-events
プロパティを使用して、SVG画像の対話性を形成する方法、つまり、ドキュメントのどの部分がクリック、タッチ、またはタップを受け取ることができるかを制御する方法を見てみましょう。下のSVG画像をクリックまたはタップしてみてください。 ポインタを正しい場所(影付きのパス)に置くと、SmashingMagazineのホームページが新しいブラウザタブで開かれるはずです。 空白をクリックしようとすると、代わりに本当に混乱する可能性があります。
これは、SVG画像内のリンクを含む最近のプロジェクトで直面したジレンマです。 画像をクリックすると、リンクが機能することがありました。 他の時にはそうではありませんでした。 紛らわしいですよね?
何が起こっているのか、そしてSVGが修正を提供するかどうかについてもっと知るために、私はSVG仕様に目を向けました。 答え: pointer-events
。
DOM( D ocument O bject M odel)ポインターイベントと混同しないように、 pointer-events
はCSSプロパティとSVG要素属性の両方です。 これにより、SVGドキュメントまたは要素のどの部分が、マウス、トラックパッド、指などのポインティングデバイスからイベントを受信できるかを管理できます。
用語に関する注意:「ポインタイベント」は、デバイスに依存しない、ユーザー入力用のWebプラットフォーム機能の名前でもあります。 ただし、この記事では、およびpointer-events
プロパティの目的で、「ポインターイベント」というフレーズにはマウスイベントとタッチイベントも含まれます。
箱の外:SVGの「形状モデル」
HTMLでCSSを使用すると、HTMLにボックスレイアウトモデルが適用されます。 ボックスレイアウトモデルでは、すべての要素がその内容の周りに長方形を生成します。 その長方形は、インライン、インラインレベル、アトミックインラインレベル、またはブロックの場合がありますが、それでも4つの直角と4つのエッジを持つ長方形です。 リンクまたはイベントリスナーを要素に追加すると、インタラクティブ領域は長方形の寸法と一致します。
注:インタラクティブ要素にclip-path
を追加すると、そのインタラクティブ境界が変更されます。 つまりa
要素に六角形のclip-path
を追加すると、クリッピングパス内のポイントのみがクリック可能になります。 同様に、スキュー変換を追加すると、長方形が菱形に変わります。
SVGにはボックスレイアウトモデルがありません。 ご覧のとおり、SVGドキュメントがHTMLドキュメントに含まれている場合、CSSレイアウト内で、ルートSVG要素はボックスレイアウトモデルに準拠します。 その子要素はそうではありません。 その結果、ほとんどのCSSレイアウト関連のプロパティはSVGには適用されません。
その代わりに、SVGには「形状モデル」と呼ぶものがあります。 リンクまたはイベントリスナーをSVGドキュメントまたは要素に追加する場合、インタラクティブ領域は必ずしも長方形である必要はありません。 SVG要素にはバウンディングボックスがあります。 バウンディングボックスは、次のように定義されます。要素とその子孫を完全に囲む、その要素のユーザー座標系の軸に位置合わせされた最もぴったりと合う長方形。
ただし、最初は、SVGドキュメントのどの部分がインタラクティブであるかは、どの部分が表示および/またはペイントされているかによって異なります。
ペイントされた要素と目に見える要素
SVG要素は「塗りつぶす」ことができますが、「ストローク」することもできます。 塗りつぶしとは、図形の内部を指します。 ストロークはその輪郭を指します。
合わせて、「塗りつぶし」と「ストローク」は、要素を画面またはページ(キャンバスとも呼ばれます)にレンダリングするペイント操作です。 ペイントされた要素について話すとき、要素に塗りつぶしやストロークがあることを意味します。 通常、これは要素も表示されることを意味します。
ただし、SVG要素は表示せずにペイントできます。 これは、 visible
されている属性値またはCSSプロパティがhidden
表示になっている場合、またはdisplay
がnone
の場合に発生する可能性があります。 要素はそこにあり、理論的な空間を占めています。 私たちはそれを見ることができません(そして支援技術はそれを検出しないかもしれません)。
おそらくもっと紛らわしいことに、要素はペイントせずにvisible
visibility
の値を計算して表示することもできます。 これは、要素にストロークと塗りつぶしの両方がない場合に発生します。
注:アルファ透明度のカラー値(例: rgba(0,0,0,0)
)は、要素がペイントされているか表示されているかに影響しません。 つまり、要素にアルファ透明の塗りまたは線がある場合、見えなくてもペイントされます。
各pointer-events
値の影響を理解するには、要素がいつペイントされるか、表示されるか、またはどちらでもないかを知ることが重要です。
全か無かの法則またはその間の何か:値
pointer-events
は、CSSプロパティとSVG要素属性の両方です。 その初期値はauto
です。これは、ペイントされた部分と表示された部分のみがポインタイベントを受け取ることを意味します。 他のほとんどの値は、次の2つのグループに分割できます。
- 要素を表示する必要がある値。 と
- そうでない値。
painted
、 fill
、 stroke
、およびall
が後者のカテゴリに分類されます。 それらの可視性に依存する対応物( visiblePainted
、 visibleFill
、 visibleStroke
、 visible
)は、前者に分類されます。
SVG 2.0仕様では、 bounding-box
値も定義されています。 pointer-events
の値がbounding-box
の場合、要素の周囲の長方形の領域もポインタイベントを受け取ることができます。 この記事の執筆時点では、Chrome65以降のみがbounding-box
の値をサポートしています。
none
も有効な値です。 要素とその子がポインタイベントを受信するのを防ぎます。 pointer-events
CSSプロパティは、HTML要素でも使用できます。 ただし、HTMLで使用する場合、 auto
とnone
のみが有効な値です。
pointer-events
値は説明よりもよく示されているので、いくつかのデモを見てみましょう。
ここに、塗りと線が適用された円があります。 塗装されて見えます。 円全体がポインタイベントを受信できますが、円の外側の領域は受信できません。
塗りつぶしを無効にして、その値がnone
になるようにします。 ここで、円の内側にカーソルを合わせたり、クリックしたり、タップしたりしようとしても、何も起こりません。 ただし、ストローク領域に対して同じことを行うと、ポインタイベントがディスパッチされます。 fill
の値をnone
に変更すると、この領域は表示されますが、ペイントされません。
マークアップに小さな変更を加えましょう。 fill=none
を維持しながら、 pointer-events="visible"
をcircle
要素に追加します。
これで、ストロークで囲まれたペイントされていない領域がポインタイベントを受け取ることができます。
SVG画像のクリック可能な領域の拡張
この記事の最初からの画像に戻りましょう。 私たちの「アメジスト」は、それぞれがstroke
とfill
を持つポリゴンのグループとは対照的に、 path
要素です。 つまり、 pointer-events="all"
を追加して1日と呼ぶことはできません。
代わりに、クリック領域を増やす必要があります。 ペイントされた要素と目に見える要素について私たちが知っていることを使用しましょう。 以下の例では、画像マークアップに長方形を追加しました。
この長方形は見えませんが、技術的には見えます(つまり、 visibility: visible
)。 ただし、塗りつぶしがないということは、塗装されていないことを意味します。 私たちの画像は同じように見えます。 実際、それでも同じように機能します。空白をクリックしても、ナビゲーション操作はトリガーされません。 要素にpointer-events
属性を追加a
必要があります。 visible
値またはall
値を使用すると、ここで機能します。
これで、画像全体がポインタイベントを受け取ることができます。
bounding-box
を使用すると、ファントム要素が不要になります。 バウンディングボックス内のすべてのポイントは、パスで囲まれた空白を含むポインタイベントを受け取ります。 しかし、繰り返しになりますpointer-events="bounding-box"
は広くサポートされていません。 それまでは、未塗装の要素を使用できます。
SVGとHTMLを混在させる場合pointer-events
使用
pointer-events
が役立つ可能性のある別のケース:HTMLボタン内でSVGを使用する。
ほとんどのブラウザ(FirefoxとInternet Explorer 11はここでは例外です)では、 event.target
の値はHTMLボタンではなくSVG要素になります。 開始SVGタグにpointer-events="none"
を追加しましょう。
これで、ユーザーがボタンをクリックまたはタップすると、 event.target
がbutton
を参照します。
DOMとJavaScriptに精通している人は、arrow関数の代わりにfunction
キーワードを使用し、 event.target
の代わりにthis
を使用すると、この問題が修正されることに気付くでしょう。 ただし、CSSでpointer-events="none"
(またはpointer-events: none;
)を使用すると、その特定のJavaScriptの癖をメモリにコミットする必要がなくなります。
結論
SVGは、HTMLで使用していたのと同じ種類の対話性をサポートします。 これを使用して、クリックまたはタップに応答するグラフを作成できます。 CSSおよびHTMLボックスモデルに準拠しないリンクされた領域を作成できます。 また、 pointer-events
を追加することで、ユーザーの操作に応じてSVGドキュメントの動作を改善できます。
SVG pointer-events
ブラウザーサポートは堅牢です。 SVGをサポートするすべてのブラウザーは、SVGドキュメントと要素のプロパティをサポートします。 HTML要素とともに使用すると、サポートの堅牢性が少し低下します。 Internet Explorer 10またはその前身、あるいはOperaMiniのどのバージョンでも利用できません。
この部分では、 pointer-events
の表面をかじったところです。 より詳細で技術的な扱いについては、SVG仕様をお読みください。 MDN(Mozilla Developer Network)Web Docsは、 pointer-events
に関するよりWeb開発者向けのドキュメントを、例とともに提供します。