h5实现移动端图片预览器(一)

最近接触vue.js移动端开发。自己写一个类似微博的图片预览器来学习一下移动端手势的实现和css3的属性的使用。

目标分析

首先分析图片预览器的功能:

1.图片显示
2.缩放(swipe)图片
3.拖拽图片(drag)
3.双击(doubleTap)放大/缩小
4.单击(tap)隐藏图片
5.左右滑到前一页或后一页

分析的手势有:单击(tap) 双击(doubleTap) 缩放(swipe) 拖拽(drag)
都是由有三个事件构成:touchstart, touchmove,touchend.

手势解析:

单击(tap)

手势分解:点击进入touchstart事件,touchmove几乎没有,但是也要为用户预留点击时的微小移动,再触发touchend事件。在本组件中touchmove移动半径设置为小于10
图片描述

从触摸屏幕到离开屏幕的时间是非常短的,所以touchstart事件到touchend事件之间的时间间隔是非常小的,不超过500毫秒。t2-t1<500
图片描述
代码实现:

 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像素内。
图片描述

实现:

 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具体实现过程

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值