手机端实现触摸拖拽效果

手机端实现触摸拖拽效果

前言

相信在开发手机端页面时,大家都会碰到拖拽元素的需求,下面我们就来介绍一下相关的实现过程,我们需要使用到touchstart,touchmove,touchend三个事件,

1.touchstart是触摸开始时触发的事件
2.touchmove是触摸移动过程中触发的事件
3.touchend是触摸结束时触发的事件

我们遇到这样一个需求,初始状态,底部会展示一小部分区域,当我们手指触摸到上面时,向上滑动,底部区域会随着手指移动而跟着向上移动
手机端实现触摸拖拽效果_第1张图片
手机端实现触摸拖拽效果_第2张图片
这里有三块,1.首页,2.底部区域,3.底部内

难点,底部区域初始态,底部区域滚动过程态,底部区域滚动终止态

底部区域初始态:首页要可滚动,底部区域要可触发,底部内要不可滚动

底部区域滚动过程态:当底部区域进行触摸跟随移动时,需要阻止首页的滚动,也需要阻止底部内的滚动,因为事件冒泡会触发滚动和触摸事件

底部区域滚动终止态:当底部区域移动到最上方时,底部内就需要可以进行滚动,

2.1当手指向上滚动时,需要阻止底部区域的触摸事件不触发,只触发底部内的滚动事件
2.2当手指向下滚动时,指直到无法在进行滚动,已经滚动到最顶部了,需要触发底部区域的触摸事件,阻止底部内的滚动事件

下图是移动到最上方的状态
手机端实现触摸拖拽效果_第3张图片

下面是我们具体实现代码

//html代码
    
//js代码
   //定义datas
    flags = false;
    position = { x: 0, y: 0 };
    nx = 0;
    ny = 0;
    dx = 0;
    dy = 0;
    xPum = 0;
    yPum = 0;
    isTouchStart = false;//是否开始触摸事件
    bottomHeight = 0; // 底部高度
    //底部内
     private get dialogContent(): HTMLElement {
        return document.getElementById('dialogContent');
    }
    //底部区域
    private get dialogWrap(): HTMLElement {
        return document.getElementById('dialogWrap');
    }
    //首页
    private get bodyEle(): HTMLElement {
        return document.body;
    }
    mounted(): void {
        this.bottomHeight = window.innerHeight / (window.innerWidth / 3.6) - 1.19;
    }
    //内部滚动
    private dialogContentScroll(e): void {
        e.stopPropagation();
        let scrollTops = Math.ceil(this.dialogContent.scrollTop); //滚动的距离
        let clientHeight = this.dialogContent.clientHeight; //窗口的高度
        let scrollHeight = this.dialogContent.scrollHeight; //内容的总高度
        // console.log('--------------------', 0, scrollTops, clientHeight, scrollHeight);
        if (scrollTops === 0) {
          // 滚动到最上方时,变为false,可以触发底部区域的触摸事件
            this.isTouchStart = false;
        } else {
        // 除了滚动到最上方时,变为true,不可以触发底部区域的触摸事件
            this.isTouchStart = true;
        }
    }
    //触摸开始
    private dialogWrapStart(event): void {
        event.stopPropagation();
        if (this.isTouchStart) {
            return;
        }
        this.bodyEle.style.overflow = 'hidden';  //阻止首页滚动
        this.dialogContent.style.overflow = 'hidden';  //阻止底部内滚动
        this.dialogWrap.style.transition = null;
        this.flags = true;
        let touch;
        if (event.touches) {
            touch = event.touches[0];
        } else {
            touch = event;
        }
        this.position.x = touch.clientX;
        this.position.y = touch.clientY;
        this.dx = this.dialogWrap.offsetLeft;
        this.dy = this.dialogWrap.offsetTop;
    }
    //触摸移动
    private dialogWrapMove(event): void {
        event.stopPropagation();
        if (this.flags) {
            let touch;
            if (event.touches) {
                touch = event.touches[0];
            } else {
                touch = event;
            }
            this.nx = touch.clientX - this.position.x;
            this.ny = touch.clientY - this.position.y;
            this.xPum = this.dx + this.nx;
            this.yPum = this.dy + this.ny;
            if (this.yPum >= 50 && this.yPum <= 650) {
                this.dialogWrap.style.top = this.yPum + 'px';
            }
            // console.log(this.yPum);
            if (this.yPum <= 600) {
                //滚动到一定距离,加载后面的模块,性能优化初始状态只加载底部区域的部分内容
                this.isScroll = true;
            }
            //阻止页面的滑动默认事件;如果碰到滑动问题,1.2 请注意是否获取到 touchmove
            document.addEventListener(
                'touchmove',
                function () {
                    event.preventDefault();
                },
                false
            );
        }
    }

    //触摸结束
    private dialogWrapEnd(): void {
        this.dialogWrap.style.transition = 'top 0.5s';
        if (this.yPum >= 400 || this.yPum === 0) {
          //底部区域随着触摸移动到手机一半以下,回到初始状态
            this.dialogWrap.style.top = this.bottomHeight + 'rem';
            this.dialogContent.style.overflow = 'hidden';//阻止底部内滚动
            this.bodyEle style.overflow = 'scroll';  //开启首页滚动
            this.$emit('hideDialog');
        } else if (this.yPum <= 400) {
          //底部区域随着触摸移动到手机一半以上,回到置顶状态
            this.dialogWrap.style.top = 0.5 + 'rem';
            this.dialogContent.style.overflow = 'scroll';//开启底部内滚动
            this.$emit('showDialog');
        }
        this.flags = false;
    }

你可能感兴趣的:(javaScript,vue,ts,javascript,vue.js,typescript)