文字版
源码
<template> <view class="content"> <view class="scrollBox"> <scroll-view class="scroll" scroll-x='true' scroll-with-animation :scroll-left='scrollLeft'> <view class="tabBox" v-for="(item,index) in tabsList" :key="index" :class="[{ active: currentIndex === index }, 'scroll-item']" @click="changeTab(index)"> <view class="nanum" :class="currentIndex === index?'active':''"> {{index+1}} </view> </view> </scroll-view> </view> </view> </template> <script> export default { data() { return { scrollWidth: 0, tabsList: [{ id: 1, name: 'tab1', }, { id: 2, name: 'tab2', }, { id: 3, name: 'tab3', }, { id: 4, name: 'tab4', }, { id: 5, name: 'tab5', }, { id: 6, name: 'tab6', }, { id: 7, name: 'tab7', }, { id: 8, name: 'tab8', }, { id: 9, name: 'tab9', } ], currentIndex: 0, scrollLeft: 0, } }, onLoad() { // 获取元素宽度 const query = uni.createSelectorQuery().select('.scroll'); query.boundingClientRect(res => { this.scrollWidth = res.width; }).exec() }, methods: { // 切换Tab changeTab(index) { console.log(index, "文字tab"); this.currentIndex = index; this.moveTo(index) }, // 当前点击的元素移动到屏幕中间 moveTo(index) { const query = uni.createSelectorQuery().in(this) query.selectAll('.scroll-item').boundingClientRect(rect => { const windowWidth = this.scrollWidth; // 获取到的屏幕宽度 let width = 0 // 计算当前点击的标签项距离左侧的距离 for (let i = 0; i < index; i++) { width += rect[i].width } // 当大于屏幕一半的宽度则滚动,否则就设置左侧位置为0 if (width > windowWidth / 2) { this.scrollLeft = width + rect[index].width / 2 - windowWidth / 2 } else { this.scrollLeft = 0 } }).exec() }, } } </script> <style scoped> .scrollBox .tabBox { width: 150rpx; height: 100%; margin-right: 10rpx; padding: 4rpx; box-sizing: border-box; background-color: #fff; margin-top: 40rpx; } .scrollBox .tabBox .nanum { width: 100%; text-align: center; font-size: 24rpx; position: absolute; bottom: 0; left: 0; height: 60rpx; line-height: 60rpx; background: #fff; } .scroll { width: 100%; white-space: nowrap; height: 100%; background-color: #eee; } .scroll view { display: inline-block; font-size: 30rpx; color: #000; position: relative; } .scroll view.active { background-color: #000000 !important; color: #fff !important; } </style>
图片版
源码
<template> <view class="content"> <view class="scrollBox"> <scroll-view class="scroll" scroll-x='true' scroll-with-animation :scroll-left='scrollLeft'> <view class="imagbx" v-for="(item,index) in tabsList" :key="index" :class="[{ active: currentIndex === index }, 'scroll-item']" @click="changeTab(index)"> <image :src="item.img" mode="widthFix"></image> <view class="nanum" :class="currentIndex === index?'active':''"> {{index+1}} </view> </view> </scroll-view> </view> </view> </template> <script> export default { data() { return { scrollWidth: 0, tabsList: [{ id: 1, name: 'img1', img: 'https://img.pconline.com.cn/images/product/1144409/201812/10/15444358345118610_800.png' }, { id: 2, name: 'img2', img: 'https://img.pconline.com.cn/images/product/1144409/201812/10/15444358345118610_800.png' }, { id: 3, name: 'img3', img: 'https://img.pconline.com.cn/images/product/1144409/201812/10/15444358345118610_800.png' }, { id: 4, name: 'img4', img: 'https://img.pconline.com.cn/images/product/1144409/201812/10/15444358345118610_800.png' }, { id: 5, name: 'img5', img: 'https://img.pconline.com.cn/images/product/1144409/201812/10/15444358345118610_800.png' }, { id: 6, name: 'img6', img: 'https://img.pconline.com.cn/images/product/1144409/201812/10/15444358345118610_800.png' }, { id: 7, name: 'img7', img: 'https://img.pconline.com.cn/images/product/1144409/201812/10/15444358345118610_800.png' }, { id: 8, name: 'img8', img: 'https://img.pconline.com.cn/images/product/1144409/201812/10/15444358345118610_800.png' }, { id: 9, name: 'img9', img: 'https://img.pconline.com.cn/images/product/1144409/201812/10/15444358345118610_800.png' } ], currentIndex: 0, scrollLeft: 0, } }, onLoad() { // 获取元素宽度 const query = uni.createSelectorQuery().select('.scroll'); query.boundingClientRect(res => { this.scrollWidth = res.width; }).exec() }, methods: { // 点击切换Tab changeTab(index) { console.log(index, "图片tab"); this.currentIndex = index; this.moveTo(index) }, // 点击元素移动到中间 moveTo(index) { const query = uni.createSelectorQuery().in(this) query.selectAll(`.scroll-item`).boundingClientRect(rect => { const windowWidth = this.scrollWidth; // 屏幕宽度 let width = 0 // 计算当前点击的标签项距离左侧的距离 for (let i = 0; i < index; i++) { width += rect[i].width } // 当大于屏幕一半的宽度则滚动,否则就设置左侧位置为0 if (width > windowWidth / 2) { this.scrollLeft = width + rect[index].width / 2 - windowWidth / 2 } else { this.scrollLeft = 0 } }).exec() }, } } </script> <style scoped> .scrollBox .imagbx { width: 150rpx; height: 100%; margin-right: 10rpx; padding: 4rpx; box-sizing: border-box; background-color: #fff; } .scrollBox .imagbx image { height: 160rpx; width: 100%; margin-bottom: 44rpx; } .scrollBox .imagbx .nanum { width: 100%; text-align: center; font-size: 24rpx; position: absolute; bottom: 0; left: 0; height: 40rpx; background: #fff; } .scroll { width: 100%; white-space: nowrap; height: 100%; background-color: #eee; } .scroll view { display: inline-block; font-size: 30upx; color: #000; position: relative; } .scroll view.active { background-color: #000000 !important; color: #fff !important; } </style>