<template>
<div class="double-scroll-wrapper" :style="{ width: wrapperWidth + 'px' }">
<!-- 顶部滚动条(悬浮) -->
<div class="scroll-bar sticky-bar" ref="topScroll" :style="{
width: scrollBarWidth + 'px',
top: stickyTop + 'px',
height: scrollbarHeight + 'px'
}">
<div class="scroll-bar-inner" :style="{ width: contentWidth + 'px' }"></div>
</div>
<!-- 内容区 -->
<div class="content-box" ref="contentScroll" :style="{
width: contentBoxWidth + 'px',
height: height + 'px'
}">
<div class="content-inner" :style="{ width: contentWidth + 'px', height: height + 'px' }">
<slot></slot>
</div>
</div>
<!-- 底部滚动条 -->
<div class="scroll-bar" ref="bottomScroll" :style="{ width: scrollBarWidth + 'px',height: scrollbarHeight + 'px' }">
<div class="scroll-bar-inner" :style="{ width: contentWidth + 'px' }"></div>
</div>
</div>
</template>
<script>
export default {
name: "DoubleScrollbar",
props: {
width: {
type: Number,
default: 1200
},
height: {
type: Number,
default: 800
},
contentWidth: {
type: Number,
default: 1500
},
stickyTop: {
type: Number,
default: 0
},
scrollbarHeight:{
type:Number,
default:20
}
},
computed: {
wrapperWidth() {
return this.width - 20;
},
contentBoxWidth(){
return this.width - 20;
},
scrollBarWidth(){
return this.width - 20;
}
},
mounted() {
const topScroll = this.$refs.topScroll;
const bottomScroll = this.$refs.bottomScroll;
const contentScroll = this.$refs.contentScroll;
this.syncScroll(topScroll, [contentScroll, bottomScroll]);
this.syncScroll(bottomScroll, [contentScroll, topScroll]);
this.syncScroll(contentScroll, [topScroll, bottomScroll]);
},
methods: {
syncScroll(source, targets) {
source.addEventListener('scroll', () => {
targets.forEach(t => {
if (t.scrollLeft !== source.scrollLeft) {
t.scrollLeft = source.scrollLeft;
}
});
});
}
}
}
</script>
<style scoped lang="scss">
.double-scroll-wrapper {
margin: 0px auto;
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.scroll-bar {
overflow-x: auto;
overflow-y: hidden;
// height: 20px;
margin: 0;
padding: 0;
background: #fff;
z-index: 10;
}
.sticky-bar {
position: sticky;
/* top 使用动态传入的 stickyTop */
left: 0;
right: 0;
margin-bottom: 10px;
}
.scroll-bar-inner {
height: 1px;
background: transparent;
}
.content-box {
overflow-x: auto;
overflow-y: hidden;
white-space: nowrap;
border: 1px solid #ccc;
margin: 0;
padding: 0;
scrollbar-width: none;
/* Firefox */
-ms-overflow-style: none;
/* IE 10+ */
}
.content-box::-webkit-scrollbar {
display: none;
/* Chrome/Safari/Opera */
}
.content-inner {
background: #f5f5f5;
display: flex;
align-items: center;
justify-content: flex-start;
}
.scroll-bar::-webkit-scrollbar {
height:12px; /* 水平滚动条高度(粗细) */
}
.scroll-bar::-webkit-scrollbar-thumb {
border-radius: 16px;
background: #bbb; /* 滚动条颜色 */
}
.scroll-bar::-webkit-scrollbar-track {
background: #eee; /* 滚动轨道颜色 */
}
</style>
vue2页面双滚动条 设置
于 2025-10-22 14:51:54 首次发布
1964

被折叠的 条评论
为什么被折叠?



