滑鼠事件 pointer-events
透過 CSS pointer-events 樣式屬性,可以在元素互相重疊時,穿透上層元素藉此點擊到下層元素,這篇教學會介紹 CSS pointer-events 樣式屬性在 SVG 元素與非 SVG 元素的差異,以及如何製作「穿透」的點擊或懸停 ( hover ) 效果。
快速導覽:
認識 pointer-events
pointer-events
是一個設定「元素是否和滑鼠互動,或特定元素與滑鼠互動」的樣式屬性,具有繼承特性,最早 pointer-events
是作用於 SVG 元素,讓使用者可以分別選取位於不同圖層的 SVG 內容,後來部分的屬性值也支援 HTML 元素,因此也常作用於「穿透」元素的特殊效果。pointer-events
具有下列幾種屬性值:
屬性值 | 說明 |
---|---|
auto | 預設值,正常與滑鼠互動 |
none | 完全不與滑鼠互動 |
visiblePainted | ( 僅適用 SVG ) 屬於 visiblePainted 屬性的內容 |
visibleFill | ( 僅適用 SVG ) 屬於 visibleFill 屬性的內容 |
visibleStroke | ( 僅適用 SVG ) 屬於 visibleStroke 屬性的內容 |
visible | ( 僅適用 SVG ) 屬於 visible 屬性的內容 |
painted | ( 僅適用 SVG ) 屬於 painted 屬性的內容 |
fill | ( 僅適用 SVG ) 屬於 fill 屬性的內容 |
stroke | ( 僅適用 SVG ) 屬於 stroke 屬性的內容 |
all | ( 僅適用 SVG ) 全部 |
非 SVG 元素使用 pointer-events
針對「非 SVG」元素,pointer-events
只能使用 auto 和 none 兩個屬性值,設定 auto 表示正常的滑鼠互動狀況,設定 none 則會完全忽略與滑鼠的互動,也無法透過 JavaScript 取得相關的滑鼠互動事件,下方範例會將寫著 banana 的綠色 div
設定為 pointer-events:none
,接著就可以在藍色 div
上觸發紅色 div
的點擊事件或 :hover
改變樣式。
<!-- HTML 程式碼 -->
<h3>目前狀態:?</h3>
<div class="a">apple</div>
<div class="b">banana</div>
<div class="c">oxxo</div>
<!-- CSS 程式碼 -->
<style>
div {
position: absolute;
width: 100px;
height: 100px;
border: 1px solid #000;
}
.a {
top: 100px;
left: 100px;
background: #f00c;
}
.a:hover {background: orange;}
.b {
top: 50px;
left: 50px;
background: #0c0c;
pointer-events: none; /* 因為不與滑鼠互動,如果滑鼠移動到 .a .b 交集處,.a 也會變色 */
}
.c {
top: 150px;
left: 150px;
background: #09fc;
}
</style>
<javascript>
let h3 = document.querySelector('h3');
let div = document.querySelectorAll('div');
div.forEach((e)=>{
e.addEventListener('click', function(){
h3.innerHTML = '目前狀態:點擊 ' + e.innerHTML;
});
e.addEventListener('mouseleave', function(){
h3.innerHTML = '目前狀態:?';
});
});
</javascript>
SVG 元素使用 pointer-events
針對「SVG」元素,pointer-events
可以根據不同 SVG 的內容屬性,決定該內容要如何與滑鼠互動,下方範例會使用兩組 SVG,分別設定針對具有 stroke 和 fill 的內容可以偵測滑鼠事件,開啟網頁後將滑鼠移動到 SVG 上,就可以發現明顯差異。
注意,因為 SVG stroke 會貼齊形狀邊緣中線,只有在外圍沒有接觸到 fill 才會有互動。
<!-- HTML 程式碼 -->
<div>滑鼠移動到黑色邊框:不會變透明<br/>滑鼠移動到紅色或綠色:會變透明</div>
<svg class="s1">
<g>
<rect x="5.5" y="5.5" fill="#f55" stroke="#0009" stroke-width="20" width="84" height="84"/>
<circle style="fill:#0c0;" cx="95" cy="87" r="54"/>
</g>
</svg>
<div>滑鼠移動到黑色邊框:會變透明<br/>滑鼠移動到紅色或綠色:不會變透明</div>
<svg class="s2">
<rect x="5.5" y="5.5" fill="#f55" stroke="#000" stroke-width="20" width="84" height="84"/>
<circle style="fill:#0c0;" cx="95" cy="87" r="54"/>
</svg>
<!-- CSS 程式碼 -->
<style>
div, svg {margin: 10px;}
svg {width: 200px;}
svg *:hover {opacity: 0.2;}
.s1 {pointer-events: fill;}
.s2 {pointer-events: stroke;}
</style>
小結
除了「穿透」的作用,由於設定了 pointer-events
之後,會連帶造成 JavaScript 也無法獲得任何滑鼠事件,所以一般來說不會特別去使用 pointer-events
,但如果是針對一些特殊版面或效果,或許可以透過 pointer-events
輕鬆實現。
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~