123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- <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>
- 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: 50rpx;
- overflow: hidden;
- }
- &-bar{
- background-color: v-bind(indicatorActiveColor);
- height: 8rpx;
- width: v-bind(indicatorBarWidth);
- border-radius: 50px;
- }
- }
- </style>
|