178 lines
4.4 KiB
Vue
178 lines
4.4 KiB
Vue
|
<template>
|
||
|
<view class="tn-scroll-list-class tn-scroll-list">
|
||
|
<scroll-view
|
||
|
class="tn-scroll-list__scroll-view"
|
||
|
scroll-x
|
||
|
:upper-threshold="0"
|
||
|
:lower-threshold="0"
|
||
|
@scroll="scrollHandler"
|
||
|
@scrolltoupper="scrollToUpperHandler"
|
||
|
@scrolltolower="scrollToLowerHandler"
|
||
|
>
|
||
|
<view class="tn-scroll-list__scroll-view__content">
|
||
|
<slot></slot>
|
||
|
</view>
|
||
|
</scroll-view>
|
||
|
|
||
|
<!-- 指示器-->
|
||
|
<view
|
||
|
v-if="indicator"
|
||
|
class="tn-scroll-list__indicator"
|
||
|
:style="[indicatorStyle]"
|
||
|
>
|
||
|
<view class="tn-scroll-list__indicator__line" :style="[lineStyle]">
|
||
|
<view class="tn-scroll-list__indicator__line__bar" :style="[barStyle]"></view>
|
||
|
</view>
|
||
|
</view>
|
||
|
</view>
|
||
|
</template>
|
||
|
|
||
|
<script>
|
||
|
export default {
|
||
|
name: 'tn-scroll-list',
|
||
|
props: {
|
||
|
// 是否显示指示器
|
||
|
indicator: {
|
||
|
type: Boolean,
|
||
|
default: true
|
||
|
},
|
||
|
// 指示器整体宽度
|
||
|
indicatorWidth: {
|
||
|
type: [String, Number],
|
||
|
default: 50
|
||
|
},
|
||
|
// 指示器滑块的宽度
|
||
|
indicatorBarWidth: {
|
||
|
type: [String, Number],
|
||
|
default: 20
|
||
|
},
|
||
|
// 指示器颜色
|
||
|
indicatorColor: {
|
||
|
type: String,
|
||
|
default: '#E6E6E6'
|
||
|
},
|
||
|
// 指示器激活时颜色
|
||
|
indicatorActiveColor: {
|
||
|
type: String,
|
||
|
default: '#01BEFF'
|
||
|
},
|
||
|
// 自定义指示器样式
|
||
|
indicatorStyle: {
|
||
|
type: Object,
|
||
|
default() {
|
||
|
return {}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
computed: {
|
||
|
// 指示器滑块样式
|
||
|
barStyle() {
|
||
|
let style = {}
|
||
|
// 获取滑动距离的比值
|
||
|
// 滑块当前移动距离与总需滑动距离(指示器的总宽度减去滑块宽度)的比值 = scroll-view的滚动距离与目标滚动距离(scroll-view的实际宽度减去包裹元素的宽度)之比
|
||
|
const scrollLeft = this.scrollInfo.scrollLeft,
|
||
|
scrollWidth = this.scrollInfo.scrollWidth,
|
||
|
barAllMoveWidth = uni.upx2px(this.indicatorWidth) - uni.upx2px(this.indicatorBarWidth);
|
||
|
const x = scrollLeft / (scrollWidth - this.scrollWidth) * barAllMoveWidth
|
||
|
style.transform = `translateX(${x}px)`
|
||
|
// 设置滑块的宽度和背景颜色
|
||
|
style.width = `${this.indicatorBarWidth}rpx`
|
||
|
style.backgroundColor = this.indicatorActiveColor
|
||
|
return style
|
||
|
},
|
||
|
// 指示器整体样式
|
||
|
lineStyle() {
|
||
|
let style = {}
|
||
|
style.width = `${this.indicatorWidth}rpx`
|
||
|
style.backgroundColor = this.indicatorColor
|
||
|
return style
|
||
|
}
|
||
|
},
|
||
|
data() {
|
||
|
return {
|
||
|
// 滑动时滑块信息
|
||
|
scrollInfo: {
|
||
|
scrollLeft: 0,
|
||
|
scrollWidth: 0
|
||
|
},
|
||
|
// 滑动区域的宽度
|
||
|
scrollWidth: 0
|
||
|
}
|
||
|
},
|
||
|
mounted() {
|
||
|
this.$nextTick(() => {
|
||
|
this.init()
|
||
|
})
|
||
|
},
|
||
|
methods: {
|
||
|
// 初始化
|
||
|
init() {
|
||
|
this.getComponentWidth()
|
||
|
},
|
||
|
// 处理滚动事件
|
||
|
scrollHandler(event) {
|
||
|
this.scrollInfo = event.detail
|
||
|
},
|
||
|
// 滚动到最左边触发事件
|
||
|
scrollToUpperHandler() {
|
||
|
this.$emit('left')
|
||
|
this.scrollInfo.scrollLeft = 0
|
||
|
},
|
||
|
// 滚动到最右边触发事件
|
||
|
scrollToLowerHandler() {
|
||
|
this.$emit('right')
|
||
|
// this.scrollInfo.scrollLeft = uni.upx2px(this.indicatorWidth) - uni.upx2px(this.indicatorBarWidth)
|
||
|
},
|
||
|
// 获取组件的宽度
|
||
|
getComponentWidth() {
|
||
|
this._tGetRect('.tn-scroll-list').then(res => {
|
||
|
if (!res) {
|
||
|
setTimeout(() => {
|
||
|
this.getComponentWidth()
|
||
|
}, 10)
|
||
|
return
|
||
|
}
|
||
|
this.scrollWidth = res.width
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
</script>
|
||
|
|
||
|
<style lang="scss" scoped>
|
||
|
|
||
|
.tn-scroll-list {
|
||
|
padding-bottom: 20rpx;
|
||
|
|
||
|
&__scroll-view {
|
||
|
display: flex;
|
||
|
flex-direction: row;
|
||
|
|
||
|
&__content {
|
||
|
display: flex;
|
||
|
flex-direction: row;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
&__indicator {
|
||
|
display: flex;
|
||
|
flex-direction: row;
|
||
|
justify-content: center;
|
||
|
margin-top: 30rpx;
|
||
|
|
||
|
&__line {
|
||
|
width: 120rpx;
|
||
|
height: 8rpx;
|
||
|
border-radius: 200rpx;
|
||
|
overflow: hidden;
|
||
|
|
||
|
&__bar {
|
||
|
width: 40rpx;
|
||
|
height: 8rpx;
|
||
|
border-radius: 200rpx;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
</style>
|