web中的移动端的Touch事件和手动实现侧边栏

web中的移动端的Touch事件和手动实现侧边栏_第1张图片
web.jpeg

Touch事件

  • 只针对移动端使用, 不支持PC端
  • 主要有三个事件
    • touchstart手指触碰屏幕的时候触发
    • touchmove手指移动的时候触发
    • touchend 手指离开的时候
 let oDiv = document.querySelector("div");

    oDiv.addEventListener("touchstart",function () {

        console.log("开始触摸");
    });

    oDiv.addEventListener("touchmove",function () {

        console.log("移动一手指");
    });

    oDiv.addEventListener("touchend",function () {

        console.log("结束触摸---")
    });

Touch事件对象

  • 我们知道PC端每一个处理事件都有一个事件对象,Touch事件也是
 let oDiv = document.querySelector("div");
    oDiv.addEventListener("touchstart",function (e) {
        e = e || window.event;
        console.log(e);
    })
web中的移动端的Touch事件和手动实现侧边栏_第2张图片
image.png

我们经常使用的就是 touches,targetToucheschangedTouches
touches:页面上(屏幕)所有的触目点
targetTouches:元素(容器盒子)上的触摸点,当touchend执行的时候,event事件里面的 targetTouches不在有触摸点对象
changedTouches:当前屏幕上刚刚接触的手指或者离开的手指
区别:
touches和targetTouches
1.如果都是将手指按到了同一个元素上, 那么这两个对象中保存的内容是一样的
2.如果是将手指按到了不同的元素上, 那么这个两个对象中保存的内容不一样
3.touches保存的是所有元素中的手指, 而targetTouches保存的是当前元素中的手指

Touch事件对象中的clientX,pageX,screenX

  • screenX/screenY是相对于屏幕左上角的偏移位
  • clientX/clientY是相对于可视区域左上角的偏移位
  • pageX/pageY是相对于内容左上角的偏移位(内容区域有可能超出屏幕)
  





下图 可以更改的解释clientX,pageX,screenX
1.红色代表screenX
2.黄色代表pageX,蓝色的长方格是 内容区域的超出了手机屏幕
3.手绘的蓝色是clientX
也可以参考JS操作html元素中clientX、offsetX、screenX、pageX的区别一文的概述

web中的移动端的Touch事件和手动实现侧边栏_第3张图片
image.png

Touch事件的点透问题

  • 当一个元素放覆盖了另一个元素, 覆盖的元素监听touch事件,而下面的元素监听click事件,并且touch事件触发后覆盖的元素就消失了, 那么就会出现点透问题

注意粉色盒子消失,log的打印情况

web中的移动端的Touch事件和手动实现侧边栏_第4张图片
点透问题.gif

需要提醒的是:这种情况不是 事件冒泡,因为2个盒子是兄弟关系,不是父子关系

出现这种情况的原因是什么呢?
原因是

1.当我们手指触摸屏幕的时候,系统会生成2个事件,一个是touch事件,一个是click事件, touch事件优先click事件执行, click事件相对会延迟 100-300毫秒

2.当touch事件执行的时候pink粉色盒子的display属性更改为none粉色盒子消失,而click事件在200毫秒之后,执行的时候,发现粉色盒子已经消失,那么click事件就会执行 对应的触摸点位置的box盒子,进而触发box盒子的click事件

如何解决?

这个解决其实就是 阻止事件扩散其实就是阻止默认事件的执行 event.preventDefault(),所以需要在 粉色盒子执行touch 和 click事件时加上

 //粉色盒子
    oTap.addEventListener("touchstart",function (event) {
        event = event || window.event;
        oTap.style.display = "none";
        //阻止事件的默认行为
        event.preventDefault();
    });

其他的一些解决方法 第三方插件 比如:Fastclick专门用来解决这个问题,Zepto插件,注意早期的Zepto没有处理这个点透问题

关于 移动端点击事件的封装

点击事件的特点
1.按下和离开时间不能太久 100 - 200ms
2.按下和离开距离不能(不能移动)太远 5px
3.单根手指

 function Tap(dom, fn) {
        if(!(dom instanceof HTMLElement)){
            throw new Error("请传入一个DOM元素");
        }
        let startX = 0;
        let startY = 0;
        let startTime = 0;
        dom.ontouchstart = function (event) {
            // 1.判断当前元素中有几根手指
            if(event.targetTouches.length > 1){
                return;
            }
            // 2.拿到手指按下的位置
            startX = event.targetTouches[0].clientX;
            startY = event.targetTouches[0].clientY;
            // 3.拿到手指按下的时间
            startTime = Date.now();
        }
        dom.ontouchend = function (event) {
            // 1.判断有几根手指离开了
            if(event.changedTouches.length > 1){
                return;
            }
            // 2.拿到离开手指的位置
            let endX = event.changedTouches[0].clientX;
            let endY = event.changedTouches[0].clientY;
            // 3.判断手指离开的位置和按下位置的距离
            if(Math.abs(endX - startX) > 5 ||
                Math.abs(endY - startY) > 5){
                return;
            }
            // 4.拿到手指离开的时间
            let endTime = Date.now();
            // 5.判断手指离开的时间和按下的时间
            if(endTime - startTime > 100){
                return;
            }
            // console.log("单击事件");
            fn && fn();
        }
    }
  • 另外的一种方式
//封装 tap事件
    function tap(element,callBack) {
        //记录刚开始的触摸时间
        let startTime = null;
        //记录结束的时间
        let endTime = null;
        //是否移动的标志
        let isMove = false;

        //触摸开始
        element.addEventListener("touchstart",function (e) {
            //获取当前的时间戳
            startTime = Date.now();
        });

        //移动
        element.addEventListener("touchmove",function (e) {
            //移动了
            isMove = true;
        });

        //结束
        element.addEventListener("touchend",function (e) {
            //获取结束的时间戳
            endTime = Date.now();

            if (endTime - startTime <= 200 && isMove === false){
                if (callBack){
                    //触摸对象返回给 回调函数
                    callBack(e);
                }

            }
            // 还原初始状态
            isMove = false;
        });

    }


手动实现侧边栏

  • 三层结构组成:有一个父级盒子Div包括一个子级盒子ul,ul移动,ul里面包括你的内容

原理:1.手指触摸屏幕 开始startY 记录位置 2.手指移动记录位置endy,其结束的偏移量offsetY = endY - startY 需要注意的是: 因为你第一次和 第二次 offsetY值不同,需要一个记录变量currentY保存上次的offsetY,这样在下次移动的时候,就是在上一次的基础上 滚动


web中的移动端的Touch事件和手动实现侧边栏_第5张图片
image.png
  • 实现


你可能感兴趣的:(web中的移动端的Touch事件和手动实现侧边栏)