资讯专栏INFORMATION COLUMN

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

Shonim / 3680人阅读

摘要:最近接触移动端开发。自己写一个类似微博的图片预览器来学习一下移动端手势的实现和的属性的使用。在发生时将坐标位置向减得到位移量。双手势单手势双手势单手势触发移动事件图片放大功能的实现我采用了的属性进行缩放,并且设置来设置缩放中心位置。

最近接触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具体实现过程

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/92795.html

相关文章

  • 移动H5周历组件

    摘要:默认可选回调函数,绑定业务数据。切换为下一周,与组件内部传入参数作用一样,该支持异步成功回调里处理自己的业务逻辑。 文档维护者:孙尊路 喜欢的话,记得star 一下噢! 适用场景 前些阵子,写了一篇《日历组件实现》的使用在线文档,遇到一个需求:实现一个H5周历来填写每周的工作日志,去网上查阅资料,发现很多示例也没有一个标准的使用文档,感觉用起来也吃力,于是乎,自己造了一个周历组件,文...

    incredible 评论0 收藏0
  • 移动H5日历组件,已废弃不在维护

    摘要:默认可选回调函数,绑定业务数据。例如某天有日程,则会在对应日期上标识出一个小红点或者其他标识,默认传入数据格式必选回调函数,当你点击或轻触某日期后执行。 文档维护者:孙尊路 喜欢的话,记得star 一下噢! 适用场景 该组件目前仅适用于移动端H5页面展示,后期高级用法中会讲述到如何基于日历基类实现自定义模板传入。(即:开发者只需要传入自己的模板即可实现出自己的优美的日历出来。) 本篇...

    Moxmi 评论0 收藏0
  • 好签H5签字SDK,支持PC实现网页手写

    摘要:好签签字是一种支持原笔迹手写的组件,支持端网页打开,提供手写签批功能,支持对文件,插入签名日期文本等内容。确定保存后签名文本框消失。支持对已签字页使用角标标注。 好签H5签字SDK是一种支持原笔迹手写的组件,支持PC端网页打开,提供手写签批功能,支持对PDF文件,插入签名、日期、文本等内容。原笔迹手写引擎是好签电子签署系统的核心技术产品之一,是南京好签软件技术有限公司自主研发的具有完全...

    junnplus 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<