horizontal-scroll.vue 5.8 KB
Newer Older
宋成林 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
<template>
    <div class="nut-hor-scroll" rel="wrapper">
        <div class="nut-hor-list" ref="list">
            <slot name="list"></slot>
            <div class="nut-hor-control" v-if="isUnMore && $slots.more && isShowLoadMore()">
                <slot name="more"></slot>
            </div>
        </div>
    </div>
</template>
<script>
export default {
    name:'nut-hor-scroll',
    props: {
        listData: {
            type: Array,
            required: true,
            default: () => []
        },
        lineSpacing: {
            type: Number,
            default: 210
        },
        stretch: {
            type: Number,
            default: 200
        },
        isUnMore: {
            type: Boolean,
            default: false
        },
        isLoading: {
            type: Boolean,
            default: false
        }
    },
    data() {
        return {
            touchParams: {
                startX: 0, 
                endX: 0, 
                startTime: 0, 
                endTime: 0
            },
            transformX: 0,
            scrollDistance: 0,
            timer: null
        }
    },
    methods: {
        isShowLoadMore() {
            this.$nextTick(() => {
                let wrapH = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
                let listH = this.listData.length * this.lineSpacing;
                if (wrapH <= listH) {
                    return true;
                } else {
                    return false;
                }
            });
        },
        setTransform(translateX = 0, type, time = 500) {
            if (type === 'end') {
                this.$refs.list.style.webkitTransition = `transform ${time}ms cubic-bezier(0.19, 1, 0.22, 1)`;
            } else {
                this.$refs.list.style.webkitTransition = '';
            }
            this.$refs.list.style.webkitTransform = `translate3d(${translateX}px, 0, 0)`;
            this.scrollDistance = translateX;
        },

        setMove(move, type, time) {
            let updateMove = move + this.transformX;
            let w = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
            let offsetWidth = this.lineSpacing * this.listData.length;
            if (type === 'end') {
                if (updateMove > 0) {
                    updateMove = 0;
                } else if (updateMove < -offsetWidth + w) {
                    if (-offsetWidth + w <= 0) {
                        updateMove = -offsetWidth + w;
                    } else {
                        updateMove = 0;
                    }
                }
                this.setTransform(updateMove, type, time)
            } else {
                let maxMove =  -offsetWidth + w;
                if (updateMove > 0 && updateMove > this.stretch) {
                    updateMove = this.stretc;
                } else if (updateMove < maxMove - this.stretch) {
                    if (maxMove <= 0) {
                        updateMove  = maxMove - this.stretch;
                    } else {
                        updateMove =  updateMove < -this.stretch ? -this.stretch : updateMove;
                    }
                }
                this.setTransform(updateMove, null, null);
            }
        },
	
	    touchStart(event) {
            event.preventDefault();

            let changedTouches = event.changedTouches[0];
            this.touchParams.startX = changedTouches.pageX;
            this.touchParams.startTime = event.timestamp || Date.now();
            this.transformX = this.scrollDistance;
        },

        touchMove(event) {

            let changedTouches = event.changedTouches[0];
            this.touchParams.lastX = changedTouches.pageX;
            this.touchParams.lastTime = event.timestamp || Date.now();
            let move = this.touchParams.lastX - this.touchParams.startX;

            this.setMove(move);
        },

        touchEnd(event) {
            event.preventDefault();

            let changedTouches = event.changedTouches[0];
            this.touchParams.lastX = changedTouches.pageX;
            this.touchParams.lastTime = event.timestamp || Date.now();
            let move = this.touchParams.lastX - this.touchParams.startX;

            let moveTime = this.touchParams.lastTime - this.touchParams.startTime;
            let w = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
            let maxMove = -this.lineSpacing * this.listData.length + w;

            // 释放跳转之类
            if (this.isUnMore && move < 0 && (move + this.transformX) < maxMove - 50) {
                //this.$emit('jump');
            }
            
            // 加载更多
            if (!this.isLoading && !this.isUnMore && move < 0 && (move + this.transformX) < maxMove + 2 * w) {
                this.$emit('loadMore');
            }

            if (moveTime <= 300) {
                move = move * 2;
                if (move < 0 && move + this.transformX < maxMove) {
                    move = maxMove - this.transformX;
                }
                moveTime = moveTime + 500;
                this.setMove(move, 'end', moveTime);
            } else {
                this.setMove(move, 'end');
            }
        }
    },

    mounted() {
        this.$nextTick(() => {
            // 监听
            this.$el.addEventListener('touchstart', this.touchStart);
            this.$el.addEventListener('touchmove', this.touchMove);
            this.$el.addEventListener('touchend', this.touchEnd);
        });
    },
    beforeDestroy() {
        // 移除监听
        this.$el.removeEventListener('touchstart', this.touchStart);
        this.$el.removeEventListener('touchmove', this.touchMove);
        this.$el.removeEventListener('touchend', this.touchEnd);
        clearTimeout(this.timer);
    }
}
</script>