一、效果展示
淘宝:
京东:
二、话不多说,直接上demo
- 案例效果
- 代码
<template>
<div class="demo-page">
<h1>滚动效果</h1>
<div class='icons-slide-wrapper'>
<div class="icons-container" ref="iconsContainer">
<div class="icon-block" v-for="(p, blockIndex) in filterList" :key="blockIndex">
<a class="icon-item" v-for="(item, itemIndex) in p" :key="item.id || itemIndex" :href="item.route" @click="toggleIconHandler(item)">
<div class="item-img">
<img :src="item.icon" alt="">
</div>
<div class="item-name">{{ item.name }}</div>
</a>
</div>
</div>
<div class="indicator-container" v-if="demoList && demoList.length > 10">
<div class="indicator-nav" ref="indicatorContainer">
<div class="nav-slide" ref="navSlide"></div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data () {
return {
demoList: [
{
id: 1,
icon: 'https://gw.alicdn.com/imgextra/i2/O1CN01qrrUAN1wRjrhtfk6Q_!!6000000006305-2-tps-183-144.png_q90.jpg_.webp',
name: '摇现金',
route: 'https://m.caihuoxia.com/u/hunter-market/index'
},
{
id: 2,
icon: 'https://gw.alicdn.com/imgextra/i2/O1CN01qrrUAN1wRjrhtfk6Q_!!6000000006305-2-tps-183-144.png_q90.jpg_.webp',
name: '百亿补贴'
},
{
id: 3,
icon: 'https://gw.alicdn.com/imgextra/i2/O1CN01qrrUAN1wRjrhtfk6Q_!!6000000006305-2-tps-183-144.png_q90.jpg_.webp',
name: '芭芭农场'
},
{
id: 4,
icon: 'https://gw.alicdn.com/imgextra/i2/O1CN01qrrUAN1wRjrhtfk6Q_!!6000000006305-2-tps-183-144.png_q90.jpg_.webp',
name: '水排序'
},
{
id: 5,
icon: 'https://gw.alicdn.com/imgextra/i2/O1CN01qrrUAN1wRjrhtfk6Q_!!6000000006305-2-tps-183-144.png_q90.jpg_.webp',
name: '饿了么'
},
{
id: 6,
icon: 'https://gw.alicdn.com/imgextra/i2/O1CN01qrrUAN1wRjrhtfk6Q_!!6000000006305-2-tps-183-144.png_q90.jpg_.webp',
name: '天天特卖'
},
{
id: 7,
icon: 'https://gw.alicdn.com/imgextra/i2/O1CN01qrrUAN1wRjrhtfk6Q_!!6000000006305-2-tps-183-144.png_q90.jpg_.webp',
name: '家电清洗'
},
{
id: 8,
icon: 'https://gw.alicdn.com/imgextra/i2/O1CN01qrrUAN1wRjrhtfk6Q_!!6000000006305-2-tps-183-144.png_q90.jpg_.webp',
name: '活动日历'
},
{
id: 9,
icon: 'https://gw.alicdn.com/imgextra/i2/O1CN01qrrUAN1wRjrhtfk6Q_!!6000000006305-2-tps-183-144.png_q90.jpg_.webp',
name: '领淘金币'
},
{
id: 10,
icon: 'https://gw.alicdn.com/imgextra/i2/O1CN01qrrUAN1wRjrhtfk6Q_!!6000000006305-2-tps-183-144.png_q90.jpg_.webp',
name: '全部频道'
},
{
id: 11,
icon: 'https://gw.alicdn.com/imgextra/i2/O1CN01qrrUAN1wRjrhtfk6Q_!!6000000006305-2-tps-183-144.png_q90.jpg_.webp',
name: '摇现金'
},
{
id: 12,
icon: 'https://gw.alicdn.com/imgextra/i2/O1CN01qrrUAN1wRjrhtfk6Q_!!6000000006305-2-tps-183-144.png_q90.jpg_.webp',
name: '百亿补贴'
},
{
id: 13,
icon: 'https://gw.alicdn.com/imgextra/i2/O1CN01qrrUAN1wRjrhtfk6Q_!!6000000006305-2-tps-183-144.png_q90.jpg_.webp',
name: '芭芭农场'
},
{
id: 14,
icon: 'https://gw.alicdn.com/imgextra/i2/O1CN01qrrUAN1wRjrhtfk6Q_!!6000000006305-2-tps-183-144.png_q90.jpg_.webp',
name: '水排序'
},
{
id: 15,
icon: 'https://gw.alicdn.com/imgextra/i2/O1CN01qrrUAN1wRjrhtfk6Q_!!6000000006305-2-tps-183-144.png_q90.jpg_.webp',
name: '饿了么'
},
{
id: 16,
icon: 'https://gw.alicdn.com/imgextra/i2/O1CN01qrrUAN1wRjrhtfk6Q_!!6000000006305-2-tps-183-144.png_q90.jpg_.webp',
name: '天天特卖'
},
{
id: 17,
icon: 'https://gw.alicdn.com/imgextra/i2/O1CN01qrrUAN1wRjrhtfk6Q_!!6000000006305-2-tps-183-144.png_q90.jpg_.webp',
name: '家电清洗'
},
{
id: 18,
icon: 'https://gw.alicdn.com/imgextra/i2/O1CN01qrrUAN1wRjrhtfk6Q_!!6000000006305-2-tps-183-144.png_q90.jpg_.webp',
name: '活动日历'
},
{
id: 19,
icon: 'https://gw.alicdn.com/imgextra/i2/O1CN01qrrUAN1wRjrhtfk6Q_!!6000000006305-2-tps-183-144.png_q90.jpg_.webp',
name: '领淘金币'
},
{
id: 20,
icon: 'https://gw.alicdn.com/imgextra/i2/O1CN01qrrUAN1wRjrhtfk6Q_!!6000000006305-2-tps-183-144.png_q90.jpg_.webp',
name: '全部频道'
},
]
}
},
methods: {
toggleIconHandler (item) {
console.log(item,'toggleIconHandlertoggleIconHandlertoggleIconHandler')
}
},
created () {
},
computed: {
filterList () {
const groupedData = []
const groupSize = 10 // 每组的大小
for (let i = 0; i < this.demoList.length; i += groupSize) {
groupedData.push(this.demoList.slice(i, i + groupSize))
}
return groupedData
}
},
mounted () {
// 获取元素引用
const iconsContainer = this.$refs.iconsContainer
const indicatorContainer = this.$refs.indicatorContainer
const navSlide = this.$refs.navSlide
// 添加滚动事件监听器
this.scrollListener = () => {
const scrollLeft = iconsContainer.scrollLeft
const containerWidth = iconsContainer.clientWidth
const totalWidth = iconsContainer.scrollWidth
const indicatorNavWidth = indicatorContainer.clientWidth
// 计算比例
const ratio = containerWidth / totalWidth
// 计算 nav-slide 的宽度和位置
const navSlideWidth = indicatorNavWidth * ratio
const maxScrollLeft = totalWidth - containerWidth
// 当前滚动位置相对于最大滚动位置的比例
const adjustedScrollLeft = Math.min(scrollLeft, maxScrollLeft)
// 动态设置 nav-slide 的宽度和位置
navSlide.style.width = navSlideWidth + "px"
// 通过 (indicatorNavWidth - navSlideWidth) 确保 nav-slide 不会超出右侧边界。
navSlide.style.transform = `translateX(${(adjustedScrollLeft / maxScrollLeft) * (indicatorNavWidth - navSlideWidth)}px)`
}
// 添加事件监听器
if (this.demoList && this.demoList.length > 10) {
iconsContainer.addEventListener("scroll", this.scrollListener)
}
},
beforeDestroy () {
// 移除事件监听器
if (this.demoList && this.demoList.length > 10) {
const iconsContainer = this.$refs.iconsContainer
iconsContainer.removeEventListener("scroll", this.scrollListener)
}
},
}
</script>
<style lang="less" scoped>
.demo-page {
margin: 0;
padding: 0;
overflow: hidden;
background: #dedede;
height: 100vh;
padding: 12px;
}
.icons-slide-wrapper {
height: auto;
width: 100%;
background-color: #FFFFFF;
overflow: hidden;
.icons-container {
display: flex;
overflow: hidden;
overflow-x: auto;
flex-wrap: nowrap;
.icon-block {
width: 100%;
display: flex;
flex-wrap: wrap;
flex: 0 0 auto;
margin-right: 10px;
.icon-item {
box-sizing: border-box;
width: 62px;
height: 62px;
padding: 0 0px 3px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #f4f4f4;
margin-right: 10px;
margin-bottom: 12px;
.item-img {
width: 42px;
height: 42px;
img {
width: 100%;
height: 42px;
object-fit: cover;
}
}
.item-name {
margin-top: 6px;
font-size: 12px;
transform: scale(0.91, 0.91);
font-family: PingFangSC, PingFang SC;
font-weight: 400;
color: #5E5E5E;
line-height: 11px;
max-width: 58px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
.icon-item:nth-child(5n) {
margin-right: 0;
}
}
.icon-block:last-child {
margin-right: 0;
}
}
.icons-container::-webkit-scrollbar {
width: 0;
/* 隐藏垂直滚动条 */
height: 0;
/* 隐藏水平滚动条 */
}
.icons-container::-webkit-scrollbar-thumb {
background-color: transparent;
/* 隐藏滚动条thumb */
}
.indicator-container {
display: flex;
width: 100%;
justify-content: center;
.indicator-nav {
width: 28px;
height: 2px;
background: #D8D8D8;
border-radius: 3px;
.nav-slide {
height: 2px;
width: 14px;
border-radius: 3px;
background-color: #fe4c1a;
will-change: transform;
}
}
}
}
</style>