h5實現移動端圖片預覽器(一)

最近接觸vue.js移動端開發。本身寫一個相似微博的圖片預覽器來學習一下移動端手勢的實現和css3的屬性的使用。css

目標分析

首先分析圖片預覽器的功能:vue

1.圖片顯示
2.縮放(swipe)圖片
3.拖拽圖片(drag)
3.雙擊(doubleTap)放大/縮小
4.單擊(tap)隱藏圖片
5.左右滑到前一頁或後一頁css3

分析的手勢有:單擊(tap) 雙擊(doubleTap) 縮放(swipe) 拖拽(drag)
都是由有三個事件構成:touchstart, touchmove,touchend.學習

手勢解析:

單擊(tap)this

手勢分解:點擊進入touchstart事件,touchmove幾乎沒有,可是也要爲用戶預留點擊時的微小移動,再觸發touchend事件。在本組件中touchmove移動半徑設置爲小於10
圖片描述spa

從觸摸屏幕到離開屏幕的時間是很是短的,因此touchstart事件到touchend事件之間的時間間隔是很是小的,不超過500毫秒。t2-t1<500
圖片描述
代碼實現:code

onTouchstart(evt){
    this.startTime = new Date().getTime();
    if(evt.touches.length>1){//雙手勢
    }else{//單手勢
         this.start.x = evt.touches[0].pageX;
         this.start.y = evt.touches[0].pageY;
    }
 }
 onTouchMove(evt){
    this.move.x =  evt.touches[0].pageX;
    this.move.y = evt.touches[0].pageY;
 }
 onTouchEnd(evt){
    let timestamp = new Date().getTime();
    if(this.move.x !== null && Math.abs(this.move.x - this.start.x)< 10 ||this.move.y !== null && Math.abs(this.move.y - this.start.y)<10){
    //有移動的狀況
    }else{
    //單擊
        if(timestamp - this.startTime < 500){
            //觸發單擊事件
        }
    }
 }

雙擊(doubleTap)
雙擊事件包含了兩次單擊事件,區分在於兩次單擊的時間判斷,兩次單擊的時間,也就是touchstart觸發的時間間隔,不超過300毫秒,固然,也要給用戶一些觸摸移動的像素,將兩個點的x,y軸上的距離控制在10像素內。
圖片描述orm

實現:對象

touchStartFn(evt){
      this.startTime = new Date().getTime();
      if(evt.touches.length>1){//雙手勢
       }else{//單手勢
            this.start.x = evt.touches[0].pageX;
            this.start.y = evt.touches[0].pageY;
            if(this.previousTouchPoint){//上一次的觸摸點
                if(Math.abs(this.start.x- this.previousTouchPoint.startX)<10 &&Math.abs(this.start.y- this.previousTouchPoint.startY)<10 && this.startTime - this.previousStartTime < 300){
                   //觸發雙擊的事件
                    ...
                }
            }
            this.previousTouchTime = this.startTime;
            this.previousTouchPoint = {
                startX:this.start.x,
                startY:this.start.y
            };
       }
   }

若是一個頁面上既有單擊tap事件,又有雙擊doubleTap事件,怎麼辦用上述方法,兩種事件會相互衝突,光靠時間和偏移量來控制是不夠的。
解決思路:初始化this.previousTouchTime = 0;this.previousTouchPoint = undefined;在執行完雙擊事件後將this.previousTouchPoint置爲undefined,this.previousTouchTime置爲0。在觸摸結束事件中添加一個setTimeout來監聽是否有新的單擊事件發生。若是新單擊事件發生,則去除這個監聽,若是沒有,則觸發單擊事件事件

touchEndFn(evt){
    let timer = setTimeout(()=>{
         if(this.previousTouchPoint !== undefined && this.previousTouchTime !== 0){
         //觸發單擊事件
         ...
         }else{
             clearTimeout(timer);//去除監聽
         }
         
    },300); 
 }

這樣,單擊和雙擊事件就不會衝突了。

縮放(swipe)

縮放是個雙手勢觸摸過程,觸摸點會有兩個,也就是Touch對象會有兩個。並在觸摸滑動過程當中,要計算出縮放倍數。
圖片描述
point1與point2的觸摸開始位置和結束位置都會有偏移,縮放的倍數計算:scale = r2/r1

onTouchStart(evt){
    if(evt.touches.length>1){//雙手勢
        let point1 = evt.touches[0];
        let point2 = evt.touches[1];
        let deltaX = Math.abs(point2.pageX - point1.pageX);
        let deltaY = Math.abs(point2.pageY - point1.pageY);
        this.distance = Math.sqrt(deltaX*deltaX+deltaY*deltaY);//初始時候的距離,r1
    }else{
    //單手勢事件
    }
}
onTouchMove(evt){
    if(evt.touches.legnth>1){
         let point1 = evt.touches[0];
        let point2 = evt.touches[1];
        let deltaX = Math.abs(point2.pageX - point1.pageX);
        let deltaY = Math.abs(point2.pageY - point1.pageY);
        let distance = Math.sqrt(deltaX*deltaX+deltaY*deltaY);
        if(this.distance){
            this.swipeScale = distance/this.distance;
            //執行縮放事件
        }
        
    }else{//單手勢事件}
}

拖拽/移動

移動事件就是在觸摸屏幕並移動的時候,圖片或者元素可以跟隨手指一塊兒移動。這是一個單手勢操做,屏幕上只要一個觸摸點。在touchmove發生時將座標位置向減獲得位移量。
圖片描述

onTouchStart(evt){
    if(evt.touches.length>1){//雙手勢
    }else{//單手勢
         this.start.x = evt.touches[0].pageX;
         this.start.y = evt.touches[0].pageY;
    }
 }
 onTouchMove(evt){
      if(evt.touches.length>1){//雙手勢
         
      }else{//單手勢
          let deltaX  = evt.touches[0].pageX - this.start.x;
          let deltaY = evt.touches[0].pageY- this.start.y;
          //觸發移動事件
      }
 }

圖片放大功能的實現

我採用了css3的transform屬性進行縮放,而且設置transform-origin來設置縮放中心位置。縮放的倍數爲縮放事件計算出的this.swipeScale
縮放代碼:

$img.style.transform = "scale("+this.swipeScale +")";
   $img.style.transformOrigin = x + " " + y;

下一節將講用vue.js具體實現過程

相關文章
相關標籤/搜索