美文网首页
移动端 局部dom实现滚动

移动端 局部dom实现滚动

作者: majunchang | 来源:发表于2019-07-19 11:31 被阅读0次

    移动端局部dom添加滑动事件

    源码

    
    /**
     * moveTopLimit: 移动过程中,随着手指的滑动 dom的偏移量
     * modifyTopLimit: 触发touchEnd的时候 我们需要进行吸顶这样的一个交互 设置吸顶的范围
     */
    export default class TouchMove {
        constructor(params) {
            this.props = params;
            this.checkParams(params);
            this.startY = 0;
            this.moveEndY = 0;
            this.oldMoveY = 0;
            this.offsetSum = 0;
            this.curDistance = 0;
            this.init();
        }
        checkParams() {
            const objectKey = [
                'Dom',
                'slider',
            ];
            const baseTypeKey = [
                'moveTopLimit',
                'moveBottomLimit',
                'modifyTopLimit',
                'modifyBottomLimit',
            ];
            objectKey.forEach((item) => {
                if (!this.props[item]) {
                    throw new Error(`${item}传参错误,请检查之后重试`);
                }
            });
            baseTypeKey.forEach((item) => {
                if (this.props[item] === undefined ||
                    (Object.prototype.toString.call(this.props[item]) !== '[object Number]'
                        && Object.prototype.toString.call(this.props[item]) !== '[object String]')) {
                    throw new Error(`${item}传参错误,请传入数字或者字符类型的数字`);
                }
            });
        }
        init() {
            this.Dom = this.props.Dom;
            this.slider = this.props.slider;
            this.moveTopLimit = parseInt(this.props.moveTopLimit, 10) || 0;
            this.moveBottomLimit = parseInt(this.props.moveBottomLimit, 10) || 0;
            this.modifyTopLimit = parseInt(this.props.modifyTopLimit, 10) || 0;
            this.modifyBottomLimit = parseInt(this.props.modifyBottomLimit, 10) || 0;
            this.addListenerWheel();
        }
        addListenerWheel() {
            this.Dom.addEventListener('touchstart', (e) => {
                this.touchStart(e);
            });
            this.Dom.addEventListener('touchmove', (e) => {
                this.touchMove(e);
            });
            this.Dom.addEventListener('touchend', (e) => {
                this.touchEnd(e);
            });
        }
        touchStart(event) {
            this.startY = parseInt(event.touches[0].clientY, 10);
            this.oldMoveY = this.startY;
        }
        touchMove(event) {
            // 当屏幕上有多个touch或者页面被缩放过 就不执行move操作
            if (event.targetTouches.length > 1 || (event.scale && event.scale !== 1)) return;
            event.preventDefault();
            this.moveY = event.touches[0].clientY;
            this.offset = (this.moveY - this.oldMoveY);
            // 获取dom当前滚动值
            this.getCurDistance();
            this.offsetSum = this.offset + this.curDistance;
            // 设置滑动范围
            if (this.offsetSum > 0) {
                this.offsetSum = Math.min(this.offsetSum, this.moveTopLimit);
            } else if (this.offsetSum < 0) {
                this.offsetSum = Math.max(this.offsetSum, this.moveBottomLimit);
            }
            this.oldMoveY = this.moveY;
            this.movePosition(this.offsetSum);
        }
        touchEnd(event) {
            this.moveEndY = parseInt(event.changedTouches[0].clientY, 10);
            this.offset = (this.moveEndY - this.startY);
            this.getCurDistance();
            this.offsetSum = this.offset + this.curDistance;
            this.movePosition(this.offsetSum, 'end');
            // 修正位置 回弹效果
            this.modifyPosition(this.offsetSum);
        }
        getCurDistance() {
            if (this.slider.style.transform) {
                this.curDistance = parseInt(
                    this.slider.style.transform.split(',')[1], 10) || 0;
            } else {
                this.curDistance = parseInt(
                    this.slider.style.webkitTransform.split(',')[1], 10) || 0;
            }
        }
        movePosition(distance) {
            this.slider.style.webkitTransform = `translate3d(0,${distance}px, 0)`;
            this.slider.style.transform = `translate3d(0,${distance}px, 0)`;
        }
        modifyPosition(distance) {
            if (distance > this.modifyTopLimit) {
                this.curDistance = this.modifyTopLimit;
                this.movePosition(this.modifyTopLimit);
            } else if (distance < this.modifyBottomLimit) {
                this.curDistance = this.modifyBottomLimit;
                this.movePosition(this.modifyBottomLimit);
            }
        }
    }
    
    
    

    如何使用

        const dom = getElementsByClassName('lose-lottery-content')[0];
                const slider = getElementsByClassName('lose-lottery-container')[0];
                const itemHeight = getElementsByClassName('lottery-item')[0].clientHeight;
                const bottomlimit =
            getElementsByClassName('lose-lottery-container')[0].clientHeight -
            getElementsByClassName('lose-lottery-content')[0].clientHeight;
                // eslint-disable-next-line no-new
                new TouchMove({
                    Dom: dom,
                    slider,
                    moveTopLimit: itemHeight,
                    moveBottomLimit: -(bottomlimit + itemHeight),
                    modifyTopLimit: 0,
                    modifyBottomLimit: -(bottomlimit + 20),
                });
    
    

    参考链接

    https://github.com/surmon-china/vue-awesome-swiper/issues/423

    相关文章

      网友评论

          本文标题:移动端 局部dom实现滚动

          本文链接:https://www.haomeiwen.com/subject/uxejlctx.html