123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- <template>
- <view class="fs-scroll-list">
- <scroll-view
- scroll-x
- :show-scrollbar="false"
- :lower-threshold="0"
- :upper-threshold="0"
- @scrolltoupper="handleToUpper"
- @scrolltolower="handleToLower"
- @scroll="handleScroll"
- >
- <view class="fs-scroll-list-content"><slot></slot></view>
- </scroll-view>
- <view class="fs-scroll-indicator" v-if="indicator">
- <view class="fs-scroll-indicator-line"><view class="fs-scroll-indicator-bar" :style="barStyle"></view></view>
- </view>
- </view>
- </template>
- <script>
- /**
- * 滚动列表组件
- * @description 滚动列表组件
- * @property {Boolean} indicator 是否显示面板指示器
- * @property {String} indicatorColor 指示器背景颜色
- * @property {String} indicatorActiveColor 指示器滑块颜色
- * @property {String} indicatorWidth 指示器的整体宽度(传值的时候需要带单位px)
- * @property {String} indicatorBarWidth 滑块的宽度(传值的时候需要带单位px)
- * @event {Function} left 滑到左边事件
- * @event {Function} right 滑动右边事件
- */
- export default {
- name: 'fs-scroll-list'
- }
- </script>
- <script setup>
- import { onMounted, reactive, ref, computed, getCurrentInstance } from 'vue'
- const props = defineProps({
- indicator: {
- type: Boolean,
- default: true
- },
- indicatorWidth: {
- type: String,
- default: '30px'
- },
- indicatorBarWidth: {
- type: String,
- default: '15px'
- },
- indicatorColor: {
- type: String,
- default: '#f2f2f2'
- },
- indicatorActiveColor: {
- type: String,
- default: '#3c9cff'
- }
- })
- const emits = defineEmits(['left', 'right'])
- const state = reactive({
- listWidth: 0,
- contentWidth: 0,
- scrollWidth: 0
- })
- onMounted(() => {
- uni
- .createSelectorQuery()
- .in(getCurrentInstance().ctx)
- .select('.fs-scroll-list')
- .boundingClientRect(data => {
- state.listWidth = data.width
- })
- .exec()
- })
- const indicatorLeftWidth = computed(() => {
- return parseInt(props.indicatorWidth) - parseInt(props.indicatorBarWidth)
- })
- const listLeftWidth = computed(() => {
- return state.contentWidth - state.listWidth
- })
- const barStyle = computed(() => {
- const x = (state.scrollWidth * indicatorLeftWidth.value) / listLeftWidth.value + 'px'
- return `transform: translateX(${x})`
- })
- const handleScroll = event => {
- state.scrollWidth = event.detail.scrollLeft
- state.contentWidth = event.detail.scrollWidth
- }
- const handleToUpper = () => emits('left')
- const handleToLower = () => emits('right')
- </script>
- <style lang="scss" scoped>
- .fs-scroll-list {
- &-box {
- display: flex;
- }
- &-content {
- display: flex;
- flex-wrap: nowrap;
- }
- }
- .fs-scroll-indicator {
- display: flex;
- justify-content: center;
- &-line {
- background-color: v-bind(indicatorColor);
- width: v-bind(indicatorWidth);
- height: 8rpx;
- border-radius: 50px;
- overflow: hidden;
- }
- &-bar {
- background-color: v-bind(indicatorActiveColor);
- height: 8rpx;
- width: v-bind(indicatorBarWidth);
- border-radius: 50px;
- }
- }
- </style>
|