使用指針事件屬性管理 SVG 交互
已發表: 2022-03-10pointer-events
屬性來塑造 SVG 圖像的交互性——即控製文檔的哪些部分可以接收點擊、觸摸或輕擊。嘗試單擊或點擊下面的 SVG 圖像。 如果您將指針放在正確的位置(陰影路徑),那麼您應該在新的瀏覽器選項卡中打開 Smashing Magazine 的主頁。 如果您嘗試單擊一些空白區域,您可能會感到非常困惑。
請參閱 CodePen 上 Tiffany Brown (@webinista) 的 Pen Amethyst。
這是我在最近的一個包含 SVG 圖像中的鏈接的項目中面臨的困境。 有時當我單擊圖像時,鏈接有效。 其他時候沒有。 令人困惑,對吧?
我轉向 SVG 規範以了解更多關於可能發生的事情以及 SVG 是否提供修復的信息。 答案: pointer-events
。
不要與 DOM(文檔對像模型)指針事件混淆, pointer-events
既是CSS屬性又是SVG元素屬性。 有了它,我們可以管理 SVG 文檔或元素的哪些部分可以接收來自指針設備(如鼠標、觸控板或手指)的事件。
關於術語的說明:“指針事件”也是與設備無關的、用於用戶輸入的 Web 平台功能的名稱。 然而,在本文中——出於pointer-events
屬性的目的——短語“指針事件”也包括鼠標和触摸事件。
開箱即用:SVG 的“形狀模型”
將 CSS 與 HTML 結合使用會在 HTML 上強加一個盒子佈局模型。 在盒子佈局模型中,每個元素都會圍繞其內容生成一個矩形。 該矩形可能是內聯、內聯級、原子內聯級或塊,但它仍然是一個具有四個直角和四個邊的矩形。 當我們向元素添加鏈接或事件偵聽器時,交互區域與矩形的尺寸相匹配。
注意:向交互元素添加clip-path
會改變其交互邊界。 換句話說,如果您將六邊形clip-path
路徑添加到a
元素,則只有剪輯路徑中的點是可點擊的。 同樣,添加傾斜變換會將矩形變成菱形。
SVG 沒有盒子佈局模型。 您會看到,當 HTML 文檔包含 SVG 文檔時,在 CSS 佈局中,根 SVG 元素遵循盒子佈局模型。 它的子元素沒有。 因此,大多數與 CSS 佈局相關的屬性不適用於 SVG。
因此,SVG 擁有我稱之為“形狀模型”的東西。 當我們向 SVG 文檔或元素添加鏈接或事件偵聽器時,交互區域不一定是矩形。 SVG 元素確實有一個邊界框。 邊界框被定義為:與該元素的用戶坐標系的軸對齊的最緊密的矩形,完全包圍它及其後代。
但最初,SVG 文檔的哪些部分是交互式的,取決於哪些部分是可見的和/或繪製的。
繪製與可見元素
SVG 元素可以“填充”,但也可以“撫摸”。 填充是指形狀的內部。 筆劃是指它的輪廓。
“填充”和“描邊”一起是繪製操作,將元素渲染到屏幕或頁面(也稱為畫布)。 當我們談論繪製元素時,我們的意思是元素具有填充和/或描邊。 通常,這意味著該元素也是可見的。
但是,可以在不可見的情況下繪製 SVG 元素。 如果visible
屬性值或 CSS 屬性被hidden
或display
為none
,則會發生這種情況。 元素在那裡並佔據理論空間。 我們只是看不到它(輔助技術可能無法檢測到它)。
也許更令人困惑的是,一個元素也可以是可見的——也就是說,有一個計算visibility
的visible
性值——而不被繪製。 當元素同時缺少描邊和填充時,就會發生這種情況。
注意:具有 alpha 透明度的顏色值(例如rgba(0,0,0,0)
)不會影響元素是否被繪製或可見。 換句話說,如果一個元素有一個 alpha 透明填充或描邊,即使看不到它也會被繪製。
了解元素何時被繪製、可見或兩者都不被繪製對於理解每個pointer-events
值的影響至關重要。
全有或無或介於兩者之間:價值觀
pointer-events
既是 CSS 屬性又是 SVG 元素屬性。 它的初始值為auto
,這意味著只有繪製的和可見的部分會接收指針事件。 大多數其他值可以分為兩組:
- 要求元素可見的值; 和
- 沒有的值。
painted
、 fill
、 stroke
, all
屬於後一類。 它們依賴於可見性的對應物—— visiblePainted
、 visibleFill
、 visibleStroke
和visible
—— 屬於前者。
SVG 2.0 規範還定義了bounding-box
值。 當pointer-events
的值為bounding-box
時,元素周圍的矩形區域也可以接收到指針事件。 在撰寫本文時,只有 Chrome 65+ 支持bounding-box
值。
none
也是一個有效值。 它防止元素及其子元素接收任何指針事件。 pointer-events
CSS 屬性也可以用於 HTML 元素。 但是當與 HTML 一起使用時,只有auto
和none
是有效值。
由於pointer-events
值的演示比解釋更好,讓我們看一些演示。
在這裡,我們有一個應用了填充和描邊的圓圈。 它既是畫的又是可見的。 整個圈子都可以接收到指針事件,但是圈子外面的區域不能。

查看 Tiffany Brown (@webinista) 在 CodePen 上用 SVG 繪製的 Pen Visible 對比。
禁用填充,使其值為none
。 現在,如果您嘗試懸停、單擊或點擊圓圈的內部,則不會發生任何事情。 但是如果你對筆劃區域做同樣的事情,指針事件仍然會被調度。 將fill
值更改為none
意味著該區域可見,但未繪製。
讓我們對標記做一個小改動。 我們將添加pointer-events="visible"
到我們的circle
元素,同時保持fill=none
。
請參閱 Tiffany Brown (@webinista) 在 CodePen 上的 Pen How 添加指針事件:所有都會影響交互性。
現在被筆劃包圍的未繪製區域可以接收指針事件。
增加 SVG 圖像的可點擊區域
讓我們回到本文開頭的那張圖。 我們的“紫水晶”是一個path
元素,而不是一組多邊形,每個多邊形都有一個stroke
和fill
。 這意味著我們不能只添加pointer-events="all"
就結束了。
相反,我們需要擴大點擊區域。 讓我們使用我們所知道的關於繪製和可見元素的知識。 在下面的示例中,我在圖像標記中添加了一個矩形。
請參閱 Tiffany Brown (@webinista) 在 CodePen 上增加 SVG 圖像的點擊區域的 Pen。
即使這個矩形是看不見的,它在技術上仍然是可見的(即visibility: visible
)。 然而,它沒有填充意味著它沒有被繪製。 我們的圖像看起來一樣。 事實上,它的工作原理仍然相同——單擊空白仍然不會觸發導航操作。 我們仍然需要為我們a
元素添加一個pointer-events
屬性。 使用visible
或all
值將在這里工作。
請參閱 Tiffany Brown (@webinista) 在 CodePen 上增加 SVG 圖像的點擊區域的 Pen。
現在整個圖像可以接收指針事件。
使用bounding-box
將消除對幻像元素的需要。 邊界框內的所有點都將接收指針事件,包括路徑所包圍的空白區域。 但同樣: pointer-events="bounding-box"
沒有得到廣泛支持。 在此之前,我們可以使用未繪製的元素。
在混合 SVG 和 HTML 時使用pointer-events
pointer-events
另一種情況:在 HTML 按鈕中使用 SVG。
請參閱 Tiffany Brown (@webinista) 在 CodePen 上的 Pen Ovxmmy。
在大多數瀏覽器中——Firefox 和 Internet Explorer 11 是例外—— event.target
的值將是一個 SVG 元素,而不是我們的 HTML 按鈕。 讓我們將pointer-events="none"
添加到打開的 SVG 標記中。
請參閱 Tiffany Brown (@webinista) 在 CodePen 上的 Pen How pointer-events: none can be used with SVG and HTML。
現在,當用戶單擊或點擊我們的按鈕時, event.target
將引用我們的button
。
精通 DOM 和 JavaScript 的人會注意到,使用function
關鍵字而不是箭頭函數和this
而不是event.target
可以解決這個問題。 但是,使用pointer-events="none"
(或 CSS 中的pointer-events: none;
)意味著您不必將特定的 JavaScript 怪癖提交到內存中。
結論
SVG 支持與 HTML 相同的交互方式。 我們可以使用它來創建響應點擊或點擊的圖表。 我們可以創建不符合 CSS 和 HTML 框模型的鏈接區域。 通過添加pointer-events
,我們可以改進 SVG 文檔響應用戶交互的方式。
瀏覽器對 SVG pointer-events
的支持非常強大。 每個支持 SVG 的瀏覽器都支持 SVG 文檔和元素的屬性。 當與 HTML 元素一起使用時,支持的健壯性稍差。 它在 Internet Explorer 10 或其前身或任何版本的 Opera Mini 中均不可用。
在這篇文章中,我們剛剛觸及了pointer-events
的表面。 如需更深入的技術處理,請通讀 SVG 規範。 MDN(Mozilla 開發者網絡)Web Docs 為pointer-events
提供了更多對 Web 開發者友好的文檔,並附有示例。