vue拽横向滚动页面组件

拖拽bar横向滚动页面组件

拖拽横向滚动页面,效果图如下

<!--
* @description 滑块滚动条
!-->
<template>
    <div ref="scrollBarBoxRef" class="scroll-bar-box">
        <div class="line"></div>
        <div v-if="isShowBar" ref="barRef" class="bar" @mousedown="startDrag" @mouseup="endDrag"></div>
    </div>
</template>

<script>
export default {
    name: 'ScrollBars',
    props: {
        // 需要滚动的容器
        scrollClassName: {
            type: String,
            default: 'scroll-container-wp'
        },
        // 外层数据变化时,用来判断是否显示滚动bar
        data: {
            type: Array,
            default: () => []
        }
    },
    data() {
        return {
            dragging: false,
            isShowBar: false,
            scrollContainerEle: null
        }
    },
    watch: {
        data: {
            handler() {
                this.$nextTick(() => {
                    this.scrollContainerEle = document.querySelector(`.${this.scrollClassName}`)
                    const scrollContainerScrollWidth = this.scrollContainerEle.scrollWidth
                    const scrollContainerClientWidth = this.scrollContainerEle.clientWidth
                    this.isShowBar = scrollContainerScrollWidth > scrollContainerClientWidth
                })
            },
            immediate: true,
            deep: true
        }
    },
    mounted() {
        this.scrollContainerEle = document.querySelector(`.${this.scrollClassName}`)
        this.scrollContainerEle.addEventListener('scroll', this.scrollContainerScroll)
        window.addEventListener('resize', this.setBarFunc)
        this.setIsShowBar()
        const resizeObserver = new ResizeObserver(entries => {
            this.setBarFunc()
        })
        resizeObserver.observe(this.scrollContainerEle)
    },
    beforeDestroy() {
        this.scrollContainerEle.removeEventListener('scroll', this.scrollContainerScroll)
        window.removeEventListener('resize', this.setBarFunc)
    },
    methods: {
        setBarFunc() {
            this.setIsShowBar()
            this.setBarPosition()
        },
        setIsShowBar() {
            const scrollContainerScrollWidth = this.scrollContainerEle.scrollWidth
            const scrollContainerClientWidth = this.scrollContainerEle.clientWidth
            this.isShowBar = scrollContainerScrollWidth > scrollContainerClientWidth
        },
        setBarPosition() {
            if (!this.isShowBar) return
            const scrollBarBoxRefWidth = this.$refs.scrollBarBoxRef.clientWidth
            const scrollContainerScrollLeft = this.scrollContainerEle.scrollLeft
            const scrollContainerScrollWidth = this.scrollContainerEle.scrollWidth
            const scrollContainerClientWidth = this.scrollContainerEle.clientWidth
            const maxScroll = scrollContainerScrollWidth - scrollContainerClientWidth
            const scrollPercentage = scrollContainerScrollLeft / maxScroll
            let left = scrollBarBoxRefWidth * scrollPercentage
            // 左间距
            if (left < 16) {
                left = 16
            }
            // 减掉bar宽度
            if (left > scrollBarBoxRefWidth - 52) {
                left = scrollBarBoxRefWidth - 52
            }
            if (this.$refs.barRef && this.$refs.barRef.style) {
                this.$refs.barRef.style.left = left + 'px'
            }
        },
        startDrag() {
            this.dragging = true
            document.addEventListener('mousemove', this.doDrag)
            document.addEventListener('mouseup', this.endDrag)
        },
        doDrag(event) {
            if (this.dragging) {
                const scrollBarBoxRefWidth = this.$refs.scrollBarBoxRef.clientWidth
                const scrollBarBoxScreenLeft = this.$refs.scrollBarBoxRef.getBoundingClientRect().left
                const barLeft = this.$refs.barRef.offsetLeft
                const scrollContainerScrollWidth = this.scrollContainerEle.scrollWidth
                const scrollContainerClientWidth = this.scrollContainerEle.clientWidth
                let left = event.clientX - scrollBarBoxScreenLeft
                if (left < 16) {
                    left = 16
                }
                if (left > scrollBarBoxRefWidth - 52) {
                    left = scrollBarBoxRefWidth - 52
                }
                if (this.$refs.barRef && this.$refs.barRef.style) {
                    this.$refs.barRef.style.left = left + 'px'
                }
                const maxScroll = scrollContainerScrollWidth - scrollContainerClientWidth
                const scrollPercentage = barLeft / (scrollBarBoxRefWidth - 52)
                this.scrollContainerEle.scrollTo({
                    left: left > 16 ? maxScroll * scrollPercentage : 0
                })
            }
        },
        endDrag() {
            this.dragging = false
            document.removeEventListener('mousemove', this.doDrag)
            document.removeEventListener('mouseup', this.endDrag)
        },
        scrollContainerScroll() {
            if (this.dragging) return
            this.setBarPosition()
        }
    }
}
</script>
<style lang="scss" scoped>
.scroll-bar-box {
    position: absolute;
    height: 13px;
    top: 0;
    left: 0;
    right: 0;
    .line {
        position: absolute;
        top: 6px;
        left: 0;
        right: 0;
        border-bottom: 1px solid #fce5c7;
    }
    .bar {
        position: absolute;
        width: 52px;
        height: 13px;
        top: 0;
        left: 16px;
        background: url('~@/assets/images/flow/ic_scroll_bar.png') no-repeat center center;
        background-size: 100% 100%;
        border-radius: 4px 0 0 4px;
        cursor: pointer;
    }
}
</style>

调用

posted @ 2024-11-22 17:33  hong_li  阅读(176)  评论(0)    收藏  举报