移動端人機交互方式同PC端發生了本質的變化,在PC端使用鼠標和鍵盤進行交互,而移動端使用的是手指的觸摸和滑動。PC端開發時主要監聽鼠標事件,例如mouseEnter(鼠標進入事件)、mouseMove(鼠標移動事件)、mouseLeave(鼠標離開事件)。而在移動端監聽事件爲觸摸的開始事件,觸摸移動事件,以及觸摸的結束事件。在本設計中商品詳情頁經過選項卡來達到切換顯示基本信息、商品細節信息以及評論信息。在基本信息經過幻燈效果顯示商品的大圖,經過手指的滑動來控制幻燈的顯示。移動端手勢操做效果圖:
git
實現的方法是監聽手勢的開始事件,記錄手指在屏幕上的起始位置。監聽手勢的移動事件,獲取移動中手指的座標,並將移動的手指座標減去起始位置的座標獲得手指移動的距離。而後實時地去改變幻燈片的transform的值來達到幻燈移動的效果。最後須要監聽手勢的結束事件,在該事件的處理函數中獲得手指最後的位置,一樣使用最後的位置減去手指的起始位置獲得最終手指移動的距離,判斷手指最終的移動距離是否大於滑動的臨界值,本設計在此處設置臨界值爲100px,若是大於臨界值則切換幻燈片,不然不進行切換。
在切換中特殊狀況是幻燈處於第一張並向左滑動,以及最後一張並向右滑動,這兩種操做都是無效的由於第一張幻燈左側以及第二張幻燈右側都是沒有圖片的。如何友好的告訴用戶已近滑動到了第一張或者最後一張是提高用戶體驗的關鍵。在本設計中借鑑了各大主流電商平臺的主流作法,即在無效滑動狀況降低低幻燈的滑動速度讓用戶知道已近沒法移動了。這種作法既保持了操做上的一致性,由於沒有直接不響應用戶的操做,又清楚明白的告訴了用戶已經滑動到了盡頭。
在PC端的開發過程當中,使用絕對定位改變top與left的值來實現元素的移動。在第一次嘗試使用絕對定位來實現,當手指滑動時改變元素的top值與left值,此時出現了元素左右抖動的狀況。由於移動端都很好的支持了CSS3與HTML5,因此在移動端開發過程當中能夠放心地使用CSS3中transform樣式,其樣式值有translate3d(三個方向的移動)、transformX(橫向的移動)、transformY(縱向的移動)、scale(2d縮放轉換)、rotate(定義2d的旋轉)等等。這裏使用translate3d來改變元素位置。transform與絕對定位在表現上的不一樣是因爲瀏覽器在樣式改變時會觸發重構與重繪,在改變絕對定位的left與top值是首先觸發了重構接着觸發重繪,而經過transform只觸發了瀏覽器的重繪。從而使用transform提升了瀏覽器的處理效率,擁有更好的性能。在實際表現中transform也可以很是完美解決問題。github
HTML結構爲:web
div.piclist-outer div.piclist-inner each singleBig in gmainImgs img(src='#{singleBig}' alt='slide img') div.piclist-signal-wrapper ul.piclist-signal each singleBig in gmainImgs li
由於使用的是Jade,因此爲上邊的格式。最外層的div是整個滑動區域,類名爲.piclist-inner的div包裹着若干個圖片,這些圖片水平並列。類名爲.piclist-signal-wrapper包裹的是當前顯示是第幾個圖片的標誌。瀏覽器
下面再來看具體js代碼:app
// @begin finger js var slidewrap=document.getElementsByClassName("piclist-outer")[0] var slideInner= document . getElementsByClassName("piclist-inner")[0] var page=0 var distanceX=0 var transX=0 var listUl=document.getElementsByClassName("piclist-signal")[0].getElementsByTagName("li") var listUlLen=listUl.length //觸摸的開始事件的處理函數 function handlestart (e) { if(e.touches.length!==1){ return } //獲取觸摸時的橫縱座標 startX=e.touches[0].pageX startY=e.touches[0].pageY slidewrap.addEventListener('touchmove',handlemove,false) // console.log("sx is: "+ startX+"sy is : " + startY) } //觸摸的移動事件處理函數 function handlemove (e) { transX = - page * screenWidth // console.log("page:"+(-page * screenWidth)) slideInner.style.transform="translate3d("+transX+"px,0,0)" var touches=e.touches if (touches&&touches.length) { distanceX=startX-touches[0].pageX // console.log("distanceX :"+distanceX) // console.log("handlemove"+transX) //若是當前是第一張幻燈或者最後一張幻燈,則讓滑動速度降爲原來的三分之一,已到達提示用戶已不可滑動。 if ((page == 0 && distanceX < 0) || (page == (listUlLen - 1) && distanceX > 0)) { distanceX=distanceX / 3 } //經過改變transform屬性值來達到移動的效果 var transX=-distanceX-page * screenWidth slideInner.style.transform="translate3d("+transX+"px,0,0)" } e.preventDefault() } //觸摸的結束事件處理函數 function handleend(argument) { transX=- page * screenWidth - distanceX var move_time =1 var move_dis=8 // console.log("move end") //若是是第一張幻燈並向左滑動或者最後一張幻燈向右滑動的狀況下,在滑動結束時顯示原先的幻燈不發生改變 if ((page == 0 && distanceX < 0) || (page == (listUlLen - 1) && distanceX > 0)) { transX=- page * screenWidth slideInner.style.transform="translate3d("+transX+"px,0,0)" return } //若是滑動的距離大於100px,則向右切換幻燈片 if (distanceX>=100) { listUl[page].style.background="#e0e0e0" page++ listUl[page].style.background="#c40000" //經過定時器實現滑動的動畫效果 var timer=setInterval(function () { slideInner.style.transform="translate3d("+transX+"px,0,0)" transX-=move_dis // console.log("transX:"+transX) // console.log("page:"+-page*(screenWidth + 1)) if (transX <= -page * (screenWidth + 1)) { clearInterval(timer) } },move_time) } //若是滑動距離小於100px,則向左切換幻燈片 else if (distanceX<=-100) { listUl[page].style.background="#e0e0e0" page-- listUl[page].style.background="#c40000" var timer=setInterval(function () { slideInner.style.transform="translate3d("+transX+"px,0,0)" transX+=move_dis // console.log("transX:"+transX) // console.log("page:"+-page*(screenWidth + 1)) if (transX >= -page * (screenWidth + 1)) { clearInterval(timer) } },move_time) } //若是滑動的距離沒有達到臨界的距離則不切換 else{ transX=- page * screenWidth slideInner.style.transform="translate3d("+transX+"px,0,0)" } }
查看完整項目能夠去個人GitHub,歡迎你們的下載、提問和關注哈。ide