zoukankan      html  css  js  c++  java
  • 移动端手势

    1. 相关事件在 mobile 与 pc 之间的差异

    1.1  click事件的300ms延迟问题:

    ​2007年第一代iphone发布,浏览器自带了一个功能:双击缩放。
    双击页面的时候,浏览器会智能的缩放当前页面到原始大小。

    ​双击缩放的原理就是,当你click一次之后,会经过300ms之后检测是否再有一次click,

    如果有的话,就会缩放页面。否则的话就是一个click事件。​

    所以,当你想执行click操作的时候,就感觉到了”卡顿”。

    1.2 dblclick事件失效:

    由于双击缩放的存在,pc端的dblclick事件也失效了。

    1.3 ​新增了touch事件

    随着触屏设备的普及,w3c为移动端web新增了touch事件。

    2.移动端 touch 事件

    2.1 touch事件包括4个事件

    touchstart:当在屏幕上按下手指时触发

    touchmove:当在屏幕上移动手指时触发

    touchend:当在屏幕上抬起手指时触发

    touchcancel:当一些更高级别的事件发生的时候会取消当前的touch操作,即触发touchcancel。(电话接入、弹出信息、暂停游戏、存档等操作)

    2.2 三个基本参数

    TouchEvent:表示触摸状态发生改变时触发的event   (通过检查触摸事件的 TouchEvent.type 属性来确定当前事件属于哪种类型。如:touchstart、touchmove)


    Touch:表示用户和触屏设备之间接触时单独的交互点(a single point of contact)

    相关参数:

    identifier:表示每 1 个 Touch 对象 的独一无二的 identifier。有了这个 identifier 可以确保你总能追踪到这个 Touch对象。
    screenX:触摸点相对于屏幕左边缘的 x 坐标。

    screenY:触摸点相对于屏幕上边缘的 y 坐标。

    clientX:触摸点相对于浏览器的 viewport左边缘的 x 坐标。不会包括左边的滚动距离。

    clientY:触摸点相对于浏览器的 viewport上边缘的 y 坐标。不会包括上边的滚动距离。

    pageX:触摸点相对于 document的左边缘的 x 坐标。 与 clientX 不同的是,他包括左边滚动的距离,如果有的话。

    pageY:触摸点相对于 document的左边缘的 y 坐标。 与 clientY 不同的是,他包括上边滚动的距离,如果有的话。

    target:总是表示 手指最开始放在触摸设备上的触发点所在位置的 element。 即使已经移出了元素甚至移出了document, 他表示的element仍然不变

    TouchList:代表一个触摸屏幕上所有触点的列表。(如果用三根手指接触屏幕,TouchList 对于每根手指都会生成一个 Touch对象, 共计 3 个)​

    3.常规 touch 事件的封装 ( 单击、长按、左滑、右滑 )

    3.1 封装前的基本使用

    $('.wrap').addEventListener('click',function(e){
          console.log(e);
          console.log('click');
        })
    
    
        // 长按(longTap)
        var longTapTimer;
        $('.wrap').addEventListener('touchstart', function (e) {
          console.log('touchstart');
          console.log(e);
          longTapTimer = setTimeout(function () {
            longTap(e);
          }, 750);
        });
        $('.wrap').addEventListener('touchmove', function (e) {
          console.log('touchmove');
          clearTimeout(longTapTimer);
        });
        $('.wrap').addEventListener('touchend', function (e) {
          console.log('touchend');
          clearTimeout(longTapTimer);
        });
    
        
        function $(select) {
          return document.querySelector(select);
        }
    
        function longTap() {
          console.log('longTap');
        }
    View Code

    3.2 封装代码

        (function (window) { //传入window,提高变量的查找效率
          function myQuery(selector) {
            //调用这个函数的原型对象上的_init方法,并返回
            return myQuery.prototype._init(selector);
          }
          myQuery.prototype = {
            _init: function (selector) {
              if (typeof selector == "string") {
                this.ele = window.document.querySelector(selector);
                return this;
              }
            },
            /*单击事件:
             * 为了规避click的300ms的延迟,自定义一个单击事件
             * 触发时间:
             *   当抬起手指的时候触发
             *   需要判断手指落下和手指抬起的事件间隔,如果小于500ms表示单击时间。
             *
             *   如果是大于等于500ms,算是长按时间
             * */
            tap: function (handler) {
              this.ele.addEventListener("touchstart", touchFn);
              this.ele.addEventListener("touchend", touchFn);
    
              var startTime, endTime;
    
              function touchFn(e) {
                e.preventDefault()
                switch (e.type) {
                  case "touchstart":
                    startTime = new Date().getTime();
                    break;
                  case "touchend":
                    endTime = new Date().getTime();
                    if (endTime - startTime < 500) {
                      handler.call(this, e);
                    }
                    break;
                }
              }
            },
            /**
             * 长按
             * @param handler
             */
            longTag: function (handler) {
              this.ele.addEventListener("touchstart", touchFn);
              this.ele.addEventListener("touchmove", touchFn);
              this.ele.addEventListener("touchend", touchFn);
              var timerId;
    
              function touchFn(e) {
                switch (e.type) {
                  case "touchstart":
                    timerId = setTimeout(function () {
                      handler.call(this, e);
                    }, 500)
                    break;
                  case "touchmove":
                    clearTimeout(timerId)
                    break;
                  case "touchend":
                    clearTimeout(timerId);
                    break;
                }
              }
            },
            /**
             * 左侧滑动。
                记录手指按下的左边,在离开的时候计算 deltaX是否满足左滑的条件
             *
             */
            slideLeft: function (handler) {
              this.ele.addEventListener("touchstart", touchFn);
              this.ele.addEventListener("touchend", touchFn);
              var startX, startY, endX, endY;
    
              function touchFn(e) {
                e.preventDefault(); // 阻止click事件(为了兼容传统手机网页的click事件)以节省内存
                var firstTouch = e.changedTouches[0];
                switch (e.type) {
                  case "touchstart":
                    startX = firstTouch.pageX;
                    startY = firstTouch.pageY;
                    break;
                  case "touchend":
                    endX = firstTouch.pageX;
                    endY = firstTouch.pageY;
                    //x方向移动大于y方向的移动,并且x方向的移动大于25个像素,表示在向左侧滑动
                    if (Math.abs(endX - startX) >= Math.abs(endY - startY) && startX - endX >= 25) {
                      handler.call(this, e);
                    }
                    break;
                }
              }
            },
            /**
             * 右侧滑动。
             *
             */
            slideRight: function (handler) {
              this.ele.addEventListener("touchstart", touchFn);
              this.ele.addEventListener("touchend", touchFn);
              var startX, startY, endX, endY;
    
              function touchFn(e) {
                e.preventDefault(); // 阻止click事件(为了兼容传统手机网页的click事件)以节省内存
                var firstTouch = e.changedTouches[0];
                switch (e.type) {
                  case "touchstart":
                    startX = firstTouch.pageX;
                    startY = firstTouch.pageY;
                    break;
                  case "touchend":
                    endX = firstTouch.pageX;
                    endY = firstTouch.pageY;
                    //x方向移动大于y方向的移动,并且x方向的移动大于25个像素,表示在向左侧滑动
                    if (Math.abs(endX - startX) >= Math.abs(endY - startY) && endX - startX >= 25) {
                      handler.call(this, e);
                    }
                    break;
                }
              }
            }
          }
          window.$ = window.myQuery = myQuery;
        })(window);
    View Code

    3.3 封装使用

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
      <style>
        * {
          margin: 0;
          padding: 0;
        }
    
        .wrap {
          margin: 100px;
           100px;
          height: 100px;
          border: 1px solid red;
        }
      </style>
    </head>
    
    <body>
    
      <div class="wrap">wrap</div>
      <script>    
    
        (function (window) { //传入window,提高变量的查找效率
          function myQuery(selector) {
            //调用这个函数的原型对象上的_init方法,并返回
            return myQuery.prototype._init(selector);
          }
          myQuery.prototype = {
            _init: function (selector) {
              if (typeof selector == "string") {
                this.ele = window.document.querySelector(selector);
                return this;
              }
            },
            /*单击事件:
             * 为了规避click的300ms的延迟,自定义一个单击事件
             * 触发时间:
             *   当抬起手指的时候触发
             *   需要判断手指落下和手指抬起的事件间隔,如果小于500ms表示单击时间。
             *
             *   如果是大于等于500ms,算是长按时间
             * */
            tap: function (handler) {
              this.ele.addEventListener("touchstart", touchFn);
              this.ele.addEventListener("touchend", touchFn);
    
              var startTime, endTime;
    
              function touchFn(e) {
                e.preventDefault()
                switch (e.type) {
                  case "touchstart":
                    startTime = new Date().getTime();
                    break;
                  case "touchend":
                    endTime = new Date().getTime();
                    if (endTime - startTime < 500) {
                      handler.call(this, e);
                    }
                    break;
                }
              }
            },
            /**
             * 长按
             * @param handler
             */
            longTag: function (handler) {
              this.ele.addEventListener("touchstart", touchFn);
              this.ele.addEventListener("touchmove", touchFn);
              this.ele.addEventListener("touchend", touchFn);
              var timerId;
    
              function touchFn(e) {
                switch (e.type) {
                  case "touchstart":
                    timerId = setTimeout(function () {
                      handler.call(this, e);
                    }, 500)
                    break;
                  case "touchmove":
                    clearTimeout(timerId)
                    break;
                  case "touchend":
                    clearTimeout(timerId);
                    break;
                }
              }
            },
            /**
             * 左侧滑动。
                记录手指按下的左边,在离开的时候计算 deltaX是否满足左滑的条件
             *
             */
            slideLeft: function (handler) {
              this.ele.addEventListener("touchstart", touchFn);
              this.ele.addEventListener("touchend", touchFn);
              var startX, startY, endX, endY;
    
              function touchFn(e) {
                e.preventDefault(); // 阻止click事件(为了兼容传统手机网页的click事件)以节省内存
                var firstTouch = e.changedTouches[0];
                switch (e.type) {
                  case "touchstart":
                    startX = firstTouch.pageX;
                    startY = firstTouch.pageY;
                    break;
                  case "touchend":
                    endX = firstTouch.pageX;
                    endY = firstTouch.pageY;
                    //x方向移动大于y方向的移动,并且x方向的移动大于25个像素,表示在向左侧滑动
                    if (Math.abs(endX - startX) >= Math.abs(endY - startY) && startX - endX >= 25) {
                      handler.call(this, e);
                    }
                    break;
                }
              }
            },
            /**
             * 右侧滑动。
             *
             */
            slideRight: function (handler) {
              this.ele.addEventListener("touchstart", touchFn);
              this.ele.addEventListener("touchend", touchFn);
              var startX, startY, endX, endY;
    
              function touchFn(e) {
                e.preventDefault(); // 阻止click事件(为了兼容传统手机网页的click事件)以节省内存
                var firstTouch = e.changedTouches[0];
                switch (e.type) {
                  case "touchstart":
                    startX = firstTouch.pageX;
                    startY = firstTouch.pageY;
                    break;
                  case "touchend":
                    endX = firstTouch.pageX;
                    endY = firstTouch.pageY;
                    //x方向移动大于y方向的移动,并且x方向的移动大于25个像素,表示在向左侧滑动
                    if (Math.abs(endX - startX) >= Math.abs(endY - startY) && endX - startX >= 25) {
                      handler.call(this, e);
                    }
                    break;
                }
              }
            }
          }
          window.$ = window.myQuery = myQuery;
        })(window);
    
    
        $("div").tap(function (e) {
          this.innerHTML = "单击"
        })
        $("div").longTag(function (e) {
          $("div").ele.innerHTML = "长按"
        })
    
        $("div").slideLeft(function (e) {
          this.innerHTML = "左滑"
        })
        $("div").slideRight(function (e) {
          this.innerHTML = "右滑"
        })
      </script>
    
    </body>
    
    </html>
    View Code

    3.4 其他事件:上滑、下滑、双击、旋转、缩放、拖动...

    4.移动端手势相关插件

     4.1 Hammer.js

    Hammer.js 中文教程

    基本使用

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
      <style>
        #myElement {
          background: silver;
          height: 300px;
          text-align: center;
          font: 30px/300px Helvetica, Arial, sans-serif;
        }
      </style>
    </head>
    
    <body>
      <div id="myElement"></div>
      <script src="https://hammerjs.github.io/dist/hammer.js"></script>
      <script>
        var myElement = document.getElementById('myElement');
        var mc = new Hammer(myElement);
        mc.on("panleft panright tap press", function (ev) {
          myElement.textContent = ev.type + " gesture detected.";
        });
      </script>
    
    </body>
    
    </html>
    View Code

    5.相关文章

    TouchEvent

    移动端交互手势详解及实现

  • 相关阅读:
    HDU1029 Ignatius and the Princess IV
    UVA11039 Building designing【排序】
    UVA11039 Building designing【排序】
    POJ3278 HDU2717 Catch That Cow
    POJ3278 HDU2717 Catch That Cow
    POJ1338 Ugly Numbers(解法二)
    POJ1338 Ugly Numbers(解法二)
    UVA532 Dungeon Master
    UVA532 Dungeon Master
    POJ1915 Knight Moves
  • 原文地址:https://www.cnblogs.com/justSmile2/p/10616658.html
Copyright © 2011-2022 走看看