pointer-events:none 限制鼠標事件及對覆蓋元素層進行穿透


一、pointer-events:none是?

pointer-events是CSS3中又一冉冉的屬性,其支持的值牛毛般多,不過大多都與SVG相關,我們可以不用理會。當下,對於偶們來講,與SVG划開界線值得一提的就是[none|auto]兩個屬性值了。其中”auto”的感覺與width屬性的”auto”類似,一般在一些特殊場合露一手,平時閨門不出,沒什么說頭。因此,一輪篩選下來,我們需要留意的只是pointer-events:none而已。

pointer-events:none是個很有意思的東西,某些情況下其精湛的表現會讓人兩眼發光。

pointer-events:none顧名思意,就是鼠標事件拜拜的意思。元素應用了該CSS屬性,鏈接啊,點擊啊什么的都變成了“浮雲牌醬油”。

嘮叨到嘴巴打結還不如一個明快的例子給力,下面是例子大放送時間。

二、pointer-events:none與乖乖的選項卡

為了更好的示意pointer-events:none的含義,我做了個選項卡的例子。

您可以狠狠地點擊這里:當前選項卡鼠標禁用demo

上下兩個選項卡,差別在何處呢?就是當前打開的選項卡下面這個應用了pointer-events:none,於是,當我們鼠標移上去的時候,會有如下的差異反應:
沒有應用pointer-events:none的選項卡鼠標經過截圖  張鑫旭-鑫空間-鑫生活
應用pointer-events:none的選項卡鼠標經過截圖 張鑫旭-鑫空間-鑫生活

下面這個打開的選項卡,鼠標移上去好像不存在一般,點擊它也是沒有任何反應。這就是pointer-events:none的作用:對鼠標事件Say GoodBye!!

哇咔咔,pointer-events:none的作用不只是禁用鏈接hover,打開鏈接等效果,是真實意義上的將onlick事件去掉了。如果您反應迅速,創新意識強的話,是不是想到可以利用pointer-events:none實現按鈕、選項卡等的禁用效果等。

我們很多時候,考慮到兼容性等原因,常常使用a標簽作為按鈕實現一些交互效果,例如新浪微博的發送按鈕:
a標簽作為按鈕 張鑫旭-鑫空間-鑫生活

其中就涉及到按鈕的禁用(沒有文字或文字個數大於140)與可用幾種狀態。而按鈕禁用狀態下點擊事件的阻止往往是使用JS實現的,而現在,有了pointer-events,我們是不是省掉這部分的腳本呢?

想法是很不錯的,然而,人生不如意事八九,事情沒有這么簡單。pointer-events:none可以直接讓鼠標事件醬油化,但是,其並不能讓鍵盤事件變成打醬油的。因為pointer-events這里是”pointer“,而不是”any“或是”every“之類。

還是上面選項卡demo的例子,對於第二個選項卡,我們使用tab鍵索引選項卡,會發現,應用了pointer-events:none聲明的選項卡可以被focus選中(虛框+特意增加的內陰影),而且回車的時候,地址欄地址后面增加了”#bound2″,如下截圖:
鍵盤事件對應用pointer-events:none元素的作用 張鑫旭-鑫空間-鑫生活
錨點出現

是不是有心情頓時涼了半截的感覺——單純的CSS禁用按鈕事件還是不靠譜啊!

矮油,古語有雲:天無絕人之路,車到山前必有路,柳暗花明又一村…… 所以,不要這么快就退卻了,腦中快快閃現我們以往頁面制作的一些經驗,想想其他方法~~

//zxx: 假設你已經有過一番不錯的思考……

不是大家有沒有研究過a標簽+disabled屬性這種組合。首先,大家都知道input[type=text|button|radio|checkbox]等控件元素完全支持disabled屬性,可以實現事件的完全禁用(附帶UI變化)。而a標簽呢則是部分瀏覽器部分支持,由於不是本文重點,這里簡單說下。a標簽應用disabled屬性是無法阻擋任何鼠標經過或是點擊事件的(雖然IE下置灰文字看上去可以禁用),因此,在實際web開發的時候,我們不對a標簽應用disabled屬性。但是,實際上,您可能不知道的是,在絕大多數瀏覽器下,a標簽應用disabled可以禁用鍵盤事件(避開tab鍵的索引)。

您可以狠狠地點擊這里:選項卡a標簽應用disabled實例

例如FireFox瀏覽器下,我們tab鍵遍歷事件元素,結果發現先前可以被鍵盤focus的“年終獎”項被直接跳過去了,無法被鍵盤捕獲。
a鏈接應用disabled后無法捕獲鍵盤響應 張鑫旭-鑫空間-鑫生活

更新於2013-04-23
今天在FireFox下重新測試,可以被鍵盤focus了,看來是火狐修復了,與Chrome等瀏覽器保持了一致。

IE瀏覽器下同樣如此。♩♫ ♬ ♪ ♩♪……心中是不是哼起歡樂的小曲呢?pointer-events:none + disabled = 完美禁用。然而,就像北京的空氣一樣,清晰的日子總是很短暫,happy ending不是這么容易來滴。

如果您在Chrome或是Safari(需要設置偏好設置)下查看上面的實例頁面,會發現應用了disabled屬性的a標簽還是可以被鍵盤捕獲(內陰影效果呈現,回車URL地址改變)。

是不是有心情頓時涼了半截的感覺——簡單地使用CSS, HTML禁用按鈕事件還是比較懸啊!

唉,不要那么容易灰心嘛,大熊被技安揍了137次還樂觀地活着,我們可以再想想其他法子嘛~~

這里就不再賣關子了。在a標簽元素的href屬性上動刀子。a標簽元素之所以能夠響應鍵盤索引,其關鍵就在於href屬性。有了這個,瀏覽器會認為這個a元素是個鏈接之類,可以跳轉,考慮到可訪問性,有必要支持鍵盤響應。否則,當作擺設元素處理。

因此……您可以狠狠地點擊這里:無href + pointer-events:none禁用demo

這下子,徹底讓IE, FireFox, Chrome等瀏覽器下的a標簽鏈接域鍵盤事件拜拜了。示例代碼如下:

<a class="tab_a tab_on" >年終獎</a>

因此,禁用a標簽鏈接或按鈕的完美組合是:pointer-events:none & without href

三、pointer-events:none情感化認識

pointer-events:none的作用是讓元素實體“虛化”。例如一個應用pointer-events:none的按鈕元素,則我們在頁面上看到的這個按鈕,只是一個虛幻的影子而已,您可以理解為海市蜃樓,幽靈的軀體。當我們用手觸碰它的時候可以輕易地沒有任何感覺地從中穿過去。

一切都是幻影!

四、pointer-events:none“幻影”特性的實際應用

上面花了不少篇幅講了如何利用pointer-events:none本身的含義實現完全禁用的a標簽按鈕效果。然而,考慮到現實情況——IE瀏覽器以及目前的Opera(11.6)都不支持改CSS3屬性,因此,a標簽按鈕禁用的實現也只能是嘴上說說,紙上寫寫而已。

但是,這里的例子是可以切切實實應用在大型web項目上的。該例子不是利用pointer-events:none的本性(禁用鼠標),而是利用其表性(幻影)。

下圖所示的這種效果目前很多地方都有見到,水平或是垂直列表的兩端(可能會有平滑滾動效果)有個白色的半透明漸變覆蓋:
列表兩端漸變覆蓋的效果截圖 張鑫旭-鑫空間-鑫生活

OK,如果是您,這里的白色半透明漸變覆蓋該如何實現?

幾年前,要實現類似這樣的效果估計得借助圖片,不過現在,可以借助CSS實現,可以參見我之前的文章:CSS實現兼容性的漸變背景效果

具體實現非重點,不展示,您有興趣可以參考下面demo頁面的源代碼。

您可以狠狠地點擊這里:pointer-events:none“幻影”應用demo

在IE瀏覽器下,filter濾鏡實現的半透明漸變背景元素本身就是鏤空的穿透的,即我們可以使用鼠標選擇或點擊半透明背景后面的元素,如下截圖:
IE瀏覽器下半透明的鏤空效果 張鑫旭-鑫空間-鑫生活

但是對於FireFox或是Chrome等現代瀏覽器,則半透明覆蓋下面的元素會被遮住,無法選擇或點擊:
現代瀏覽器半透明覆蓋無法穿透 張鑫旭-鑫空間-鑫生活

此時,我們可以利用pointer-events:none的“幻影”特性,對半透明覆蓋元素應用pointer-events:none聲明使其可以鼠標穿透,於是,半透明覆蓋后面的文字可以選擇了,鏈接也可以點擊了:
pointer-events:none應用后的穿透性 張鑫旭-鑫空間-鑫生活

五、兼容性

目前FireFox瀏覽器,Chrome都支持。Opera以及IE不支持。

六、pointer-events擴展之瀏覽器支持的JS判斷

考慮到某些瀏覽器不支持CSS3 pointer-events屬性,因此,在實際應用的時候,可能要對不同瀏覽器做不同處理,這個時候就需要判別當前用戶瀏覽器是否支持pointer-events. 下面就是JS實現驗證的代碼:

var supportsPointerEvents = (function(){
  var dummy = document.createElement('_');
  if(!('pointerEvents' in dummy.style)) return false;
  dummy.style.pointerEvents = 'auto';
  dummy.style.pointerEvents = 'x';
  document.body.appendChild(dummy);
  var r = getComputedStyle(dummy).pointerEvents === 'auto';
  document.body.removeChild(dummy);
  return r;
})();

上面的代碼其實對於瀏覽器是否支持其他CSS3屬性也是比較受用的。

該驗證idea來自 Martin Auswöger (https://github.com/ausi/Feature-detection-technique-for-pointer-events)

七、pointer-events擴展之幻影特性的JS替代實現

直接代碼(基於jQuery):

function noPointerEvents (element) {
    $(element).bind('click mouseover', function (evt) {
        this.style.display = 'none';
        var x = evt.pageX, y = evt.pageY,
	    under = document.elementFromPoint(x, y);
        this.style.display = '';
        evt.stopPropagation();
        evt.preventDefault();
        $(under).trigger(evt.type);
    });
}

上面展示代碼中有個比較有意思的方法就是elementFromPoint,這東西兼容性還是很不錯的。具體可參見我之前這篇“CSSOM視圖模式(CSSOM View Module)相關整理”(較長)中的Part 三部分,有demo示意。

八、小賣弄:a標簽按鈕完全禁用實例

最后,小小賣弄下,綜合本文雜七雜八的內容,做個可能沒多大實際意義的實例,就是上面嘮叨了很多的a標簽按鈕完全禁用效果。

按鈕UI借鑒新浪微博。

您可以狠狠地點擊這里:a標簽按鈕完全禁用demo賣弄版

:本demo是為了應用CSS3 pointer-events屬性而使用了pointer-events,實際應用無需如此折騰。

本demo應用了上面瀏覽器是否支持pointer-events屬性的JS擴展。完整JavaScript代碼如下:

var supportsPointerEvents = (function(){
    //上面驗證瀏覽器支持pointer-events屬性代碼
})();

var oArea = document.getElementById("testArea"),
     oButton = document.getElementById("testButton");

oArea.onkeyup = function() {
    var length = this.innerHTML.length;
    if (length == 0 || length > 140) {
        oButton.className = "test_button test_button_disabled";
        oButton.removeAttribute("href");	
    } else {
        oButton.className = "test_button";
        oButton.href = "javascript:";		
    }
};

oButton.onclick = function() {
    //如果支持CSS3 pointer-events,CSS自動判定是否執行點擊事件,腳本這邊可以無顧忌執行彈出
    //如果不支持CSS3 pointer-events
    //通過按鈕狀態判定是否彈出
    if (supportsPointerEvents || (!supportsPointerEvents && this.href)) {
        alert("發送成功");
    }
    return false;
};

通過控制href屬性實現完全意義上的禁用。

九、結束語

本文原本計划寫個短篇的,可寫着寫着就脹出來了。其他俗耐的話就省了。本文雖然題為pointer-events,實際該屬性不管他也不妨,畢竟是新事物。然而,本文相關旁擊側敲的些內容倒是很有用,希望不要看題思意,憑空揣摩,遺漏真正有用的東西。

感謝閱讀!

原創文章,轉載請注明來自張鑫旭-鑫空間-鑫生活[http://www.zhangxinxu.com]
本文地址:http://www.zhangxinxu.com/wordpress/?p=2091


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM