1. 程式人生 > >處理粘性的4種新方法:在移動裝置上懸停效果

處理粘性的4種新方法:在移動裝置上懸停效果

CSS的古老之處:懸停偽類構成了許多CSS效果的支柱,當滑鼠滾過頁面上的元素時觸發。在當今不斷變化的環境中,觸控式螢幕輸入與滑鼠共享中心舞臺,這給網站管理員帶來了一些難題。基於觸控的裝置努力不被冷落,這種普遍的CSS功能確實可以響應懸停,但是對於它們來說唯一可行的方式是“點選”而不是實際的“懸停”。雖然這總體上是一件好事,但它會導致這些裝置上所謂的“粘滯懸停”問題:hover樣式與使用者剛剛點選的元素保持一致,直到他/她再次點選文件中的其他位置,或者在某些情況下,在效果被取消之前重新載入頁面。這種“永遠線上”的懸停效果在某些情況下是良性的,但對其他人的使用者體驗是有害的甚至是有害的。例如,頁面上的一組“volumn”按鈕具有“懸停”效果,可以改變滑鼠使用者的背景顏色,當滑鼠滑過按鈕時,效果會通知使用者按鈕可以與之互動,但是觸控裝置背景顏色“粘在”按鈕上的按鈕,它誤導使用者認為單擊一下後音量不斷增大或減小。

在本教程中,我們將介紹4種不同的方法來禁用或修改:hover移動裝置上的預設效果,以便跨平臺提供更好的使用者體驗。我們將從最保守的方法開始,然後再投入更加雄心勃勃的事情 ,同時考慮支援觸控式螢幕和滑鼠/觸控板輸入和實時的混合裝置。讓我們滾動。

方法1-有條件地將“ non-touch”CSS類新增到文件根元素

首先,一種保守的方法:hover,通過non-touch在裝置被視為不支援時向根<html>元素新增任意CSS類(即:“ ”),將CSS 樣式限制為所謂的基於滑鼠的裝置(即:桌面)。觸控”。一個COM週一方法是使用JavaScript來作出這樣的判斷:

1

2

3

4

var touchsupport = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0)

if (!touchsupport){ // browser doesn't support touch

document.documentElement.className += " non-touch"

}

non-touch現在只有在使用JavaScript測試觸控支援時返回false的裝置的“ ”類,我們:hover

才會修改相關樣式以僅定位這些裝置:

1

2

3

html.nontouch nav a:hover{ /* hover effect only visible to devices that report back as not supporting touch */

background: yellow;

}

這種方法簡單而簡潔,但並非沒有缺陷。準確地檢測觸控支援是非常困難的使用當前瀏覽器的API,並且將存在這樣的情況:不支援觸控的瀏覽器(或反之亦然)將報告相反的情況。然而,總體而言,這種方法確實達到了“足夠好”的門檻,其中:hover 效果不會影響使用者體驗 - 無論是橫向還是負面 - 無論如何都要跨平臺。

方法2-有條件地將“ can-touch”CSS類新增到文件根元素

與第一種方法相反,這種方法可以讓您:hover單獨保留原始樣式,而是:hover 針對觸控裝置製作定製 樣式。我們將利用JavaScript的“ touchstart”事件,當用戶與啟用觸控的裝置上的螢幕進行聯絡時呼叫該事件,首先實時確定裝置確實支援觸控輸入,然後再將“ can-touch”類新增到文件根元素。

1

2

3

4

6

<script>

document.addEventListener('touchstart', function addtouchclass(e){ // first time user touches the screen

document.documentElement.classList.add('can-touch') // add "can-touch" class to document root using classList API

document.removeEventListener('touchstart', addtouchclass, false) // de-register touchstart event

}, false)

</script>

使用者第一次觸控式螢幕幕時,CSS類“ can-touch”被新增到根元素,表示裝置是基於觸控的。我們使用classList API- 它在移動瀏覽器上享有極好的支援 - 更優雅地將類新增到元素中。為了防止動作超出一次,我們立即從事件中取消註冊已分配的功能。

通過此設定,我們可以:hover正常定義我們的初始樣式,然後在觸控裝置之後撤消或修改它,例如:

1

2

3

4

6

7

8

9

10

11

12

ul li a{

padding: 10px;

display: block;

}

ul li a:hover{

background: yellow;

}

html.can-touch ul li a:hover{

background: none; /* disable hover effect on touch devices */

}

這種方法可以說比分離觸控和非觸控裝置的第一種更準確,儘管它確實需要使用者在它開始之前先觸控式螢幕幕。為了處理 :hover按需發生的效果,它可以工作,儘管取決於正常和“可以觸控”之間的樣式差異:懸停類,頁面佈局的短暫轉換可能會發生,因為後者應用於頁面按需。此外,請注意,所有移動瀏覽器都不支援觸控事件,如“ touchstart” ,IE和Firefox移動顯然是其中兩個。

方法3-使用CSS媒體查詢級別4互動媒體功能

CSS Media Queries Level 4增加了對識別使用者輸入裝置功能的支援。出於我們的目的,我們對“ pointer”和“ hover” 感興趣,它告訴我們使用者主要輸入裝置的精確程度以及它支援懸停的程度。檢視以下CSS媒體查詢以及它們有助於隔離的輸入裝置型別:

1

2

3

4

6

7

8

9

10

11

12

13

14

15

16

17

18

19

@media (pointer:coarse) {

/* Primary Input is a coarse pointer device such as touchscreen or XBox Kinect etc */

}

@media (pointer:fine) {

/* Primary Input is a fine pointer device such as a mouse or stylus */

}

@media (hover:none) {

/* Primary Input doesn't respond to hover at all, even partially (ie: there is no pointing device) */

}

@media (hover:on-demand) {

/* Primary Input responds to hover only via emulation, such as touch screen devices */

}

@media (hover:hover) {

/* Primary Input responds to hover fully, such as a mouse or a Nintendo Wii controller */

}

例如,您可以:hover 在媒體查詢(@media hover:hover{})中定義常規樣式,以將它們限制為:hover完全支援的裝置(配備滑鼠或某些指標裝置的裝置):

1

2

3

4

@media (hover:hover) {

nav a:hover{

background: yellow;

}

}

或離開你原來的更加漸進的方式 :hover風格不變,目標不支援裝置的 :hover pletely:

1

2

3

4

@media (hover:none), (hover:on-demand) {

nav a:hover{ /* suppress hover effect on devices that don't support hover fully

background: none;

}

}

所有上述邏輯也可以使用JavaScript打包 ,例如:window.matchMedia()

1

var nofullhover = window.matchMedia("(hover:none), (hover:on-demand)").matches //returns true or false

雖然你可能認為你已經到達了檢測:hover支援的聖盃 - 使用CSS Media Queries Level 4-但現實並未完全符合其潛力。首先是媒體查詢4級互動媒體功能的不穩定瀏覽器支援。目前沒有Firefox瀏覽器(最高為FF 50)支援它,這幾乎使得這種方法在該領域的改進之前不切實際。其次,媒體查詢4級互動媒體功能的當前規範在我看來對前兩種處理方法提供的優勢很小:hover跨平臺的行為,除了它的優雅和沒有JavaScript依賴。所有3種方法,無論它們在檢測觸控還是無觸控支援方面都是準確的,都忽略了一種越來越受歡迎的設定,其中該裝置同時支援觸控式螢幕和滑鼠/觸控板。在這種情況下,上述檢測方案中沒有一個能夠實時確定使用者 當前正在使用哪個輸入,而是僅在將裝置報告為“觸控”時僅檢視他們認為是裝置的主要輸入的內容。 “或”沒有觸控/滑鼠“。這意味著在大多數情況下,具有觸控和滑鼠輸入的膝上型電腦將始終作為觸控裝置進行歸類,有時根據具體設定,“滑鼠”裝置, :hover無論使用者當前使用什麼輸入,相關的樣式只能滿足其中一個輸入。這顯然是一大短COM ING,一個通向下面我最後的檢測方法。

方法4- can-touch根據當前使用者輸入型別動態新增或刪除“ ”類

對於這最後的方法,我把它視為挑戰 é了一種方法來確定使用者是否使用了實時地觸控或滑鼠/觸控板基於輸入。如上所述,到目前為止我們看到的所有先前檢測方法在判斷使用者當前使用的輸入型別時都是靜態的; 當面對支援觸控和非觸控輸入的混合裝置以及使用者可以隨時在這些輸入之間切換的事實時,就像他們所說的那樣,“休斯頓我們遇到了問題”。目前所有可用的瀏覽器API只能告訴我們使用者裝置支援的輸入型別而不是他/她目前正在使用的輸入型別,現在是時候進行一些越野編碼以試圖規避這種限制。

實時檢查使用者輸入型別背後的基本思想很簡單,魔鬼就是細節。我們已經擁有上面方法2中的一半神奇公式,我們轉向JavaScript的“ ontouchstart”事件處理程式,以便在使用者與螢幕進行聯絡時通知(因此當時正在使用觸控)。但是當用戶切換到滑鼠/觸控板時呢?第一個想法自然就是參加JavaScript的滑鼠相關事件之一 - “ mouseover”,“ mousemove”,“ mouseenter”等 - 以幫助我們撥打電話,但是一旦你意識到觸控式螢幕裝置也響應滑鼠事件,那麼興奮是短暫的(很像CSS:hover每當使用者點選螢幕時,就會侵蝕觸控裝置上所有這些事件之間的區別。

因此,顯然試圖告訴滑鼠事件是由實際滑鼠/觸控板觸控何時觸控觸控式螢幕上的觸控要比看到它更難,儘管一切都沒有丟失。我發現當在頁面上註冊了“ touchstart”和滑鼠事件(如“ mouseover”)時,當用戶觸控式螢幕幕時觸發的兩個事件的順序始終是前者,後面是後一個事件:

1

2

document.addEventListener('touchstart', functionref, false) // on user tap, "touchstart" fires first

document.addEventListener('mouseover', functionref, false) // followed by mouse event, ie: "mouseover"

我們可以利用這個可預測的事件序列來區分文件上的實際觸控與實際滑鼠懸停(即:在混合裝置上),通過在發射時暫時阻止第一個事件阻止第二個事件來指示這是觸控事件,過濾掉真正的滑鼠懸停事件。讓我們來看看這一切是如何COM上課共同創造的程式碼,動態新增或刪除“ can-touch”類文件根目錄,以反映此時的使用者的當前輸入型別:

1

2

3

4

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

三十

<script>

;(function(){

var isTouch = false //var to indicate current input type (is touch versus no touch)

var isTouchTimer

var curRootClass = '' //var indicating current document root class ("can-touch" or "")

function addtouchclass(e){

clearTimeout(isTouchTimer)

isTouch = true

if (curRootClass != 'can-touch'){ //add "can-touch' class if it's not already present

curRootClass = 'can-touch'

document.documentElement.classList.add(curRootClass)

}

isTouchTimer = setTimeout(function(){isTouch = false}, 500) //maintain "istouch" state for 500ms so removetouchclass doesn't get fired immediately following a touch event

}

function removetouchclass(e){

if (!isTouch && curRootClass == 'can-touch'){ //remove 'can-touch' class if not triggered by a touch event and class is present

isTouch = false

curRootClass = ''

document.documentElement.classList.remove('can-touch')

}

}

document.addEventListener('touchstart', addtouchclass, false) //this event only gets called when input type is touch

document.addEventListener('mouseover', removetouchclass, false) //this event gets called when input type is everything from touch to mouse/ trackpad

})();

</script>

嘗試一下現場演示以上在桌面上,觸控裝置和混合裝置,看的CSS如何:hover影響是每當觸控用於與連結互動,但活躍起來,如果滑鼠或觸控板來代替上課處於休眠狀態。讓我們分解它的工作原理:

  • 我們在文件上註冊兩個事件“ touchstart”和“ mouseover”,以便在使用者與頁面互動時捕獲兩種型別的事件。
  • 在非觸控裝置(如桌面)上,只會mouseover觸發“ ”事件。removetouchclass() 雖然什麼都不做,但呼叫該函式,因為isTouch和 curRootClass變數將始終分別為false 和""(空字串)。換句話說,沒有“ can-touch”類被新增到文件中。
  • 在觸控裝置(包括使用者當前正在使用“觸控”時的混合裝置)上,觸控時觸發“ touchstart”和“ mouseover”事件,前者隨後觸發。
  • 每當使用者觸控式螢幕幕時,呼叫函式 addtouchclass()isTouch 變數設定true為在將“ can-touch”CSS類新增到面向根之前將當前輸入型別指示為觸控。為了防止removetouchclass() 在同一個觸控操作期間呼叫函式並撤消剛剛完成的操作,我們新增以下行以 addtouchclass() isTouch變數的狀態保持為真500毫秒:isTouchTimer = setTimeout(function(){isTouch = false}, 500) 使用上面的關鍵程式碼行,當removetouchclass() 也嘗試緊跟在“ touchstart”之後執行(因為觸控裝置也響應滑鼠事件),它被阻止,因為此時的值isTouch仍然為真。不久之後,isTouch變數將自身重置為false在每次觸控動作之後再次確保在使用觸控輸入後isTouch不會永久停留在該 true狀態,並且如果使用者之後切換到它(例如在混合裝置上),則可以繼續對可能的滑鼠/觸控板輸入作出反應,然後打電話removetouchclass() 。

所有這些最終導致can-touch在文件中實時新增或刪除“ ”類以反映使用者當前正在使用的輸入裝置。從我的測試,似乎整個每臺裝置我把它那可預見的工作支援JavaScript觸控事件,但留下一個 COM下面包換,如果你發現,否則。

 結論

在本教程中,我們研究了4種不同的方法來解決:hover移動裝置上的棘手問題,從不同的角度進行,以檢測使用者的輸入裝置何時觸控與非觸控。直到觸控裝置支援實際懸停(可能使用相機檢測手指何時在元素上徘徊),它們允許我們在 不同平臺上建立更好的體驗,具有不同程度的準確性和易於實現。在許多情況下,它比什麼都不做要好。