最近有个需求,需要实现card模式轮播图,每个card大小一样且有间距,本想着用element-ui跑马灯组件Carousel做的,但是试了下达不到我要的效果,于是自己手写,下面先上效果图:
实现思路:
1.首先使用flex布局+transition动画定义一个简单轮播
2.在原有list基础上前后各追加2个item,比如:[4,5,1,2,3,4,5,1,2],当index=-1或index=5时进行重置处理(-1重置为4,5重置为0),视觉上感觉是无缝切换的。
完整代码:
<div class="swiper-box">
<div class="prev-btn" @click="changeSwiper(-1)">
<img src="@/assets/image/newIcon/market/left-icon.png" alt="">
</div>
<div class="next-btn" @click="changeSwiper(1)">
<img src="@/assets/image/newIcon/market/right-icon.png" alt="">
</div>
<div class="swiper-list" :style="{left: swiperLeft, transition: transition}">
<div class="swiper-item" v-for="(item, index) in swiperList" :key="index"
:class="{active: swiperIndex+2 == index}" :style="{'background-image': `url(${item.banner})`}">
<h3>{{ item.name }}</h3>
<p>{{ item.desc }}</p>
</div>
</div>
</div>
data() {
return {
tabList: [
{ name: '快速下单', value: 'check', desc: '实现客户ERP物料与平台商品的准确匹配,无需反复搜索,实现快速下单。', banner: require('../../assets/image/newIcon/market/feature-1.jpg') },
{ name: '创业团队', value: 'team', desc: '打造大众创业的服务平台;本着“客户至上”的理念,提供线下招商、销售、售后等环节的专业化服务及解决方案。', banner: require('../../assets/image/newIcon/market/feature-2.jpg') },
{ name: '数据支持', value: 'data', desc: '汇集海量日常销售数据并提供多个维度、多种形式的可视化图表分析。', banner: require('../../assets/image/newIcon/market/feature-3.jpg') },
{ name: '品类齐全', value: 'whole', desc: '覆盖钢铁行业各工序全流程,汇聚优质产品,实现钢企一站式采购。', banner: require('../../assets/image/newIcon/market/feature-4.jpg') },
{ name: '铁信支付', value: 'tx', desc: '除了传统的支付方式,我们还支持铁信支付,河钢铁信是河钢集团推出的电子交易凭证,铁信不仅可以融资、转让,还可以在超市进行备品备件和劳保办公产品购买。', banner: require('../../assets/image/newIcon/market/feature-5.jpg') },
],
tabIndex: 0,
swiperList: [],
swiperIndex: 0,
transition: 'all 0.3s',
}
},
computed: {
swiperLeft() {
return -((this.swiperIndex+2) * (12+0.4) - 3.6) + 'rem'
}
},
mounted () {
const list = [
...this.tabList.slice(-2),
...this.tabList,
...this.tabList.slice(0, 2)
]
this.swiperList = list
},
methods: {
changeSwiper(type) {
// 防抖
if(!debounce(360)){
return
}
if (type === 1) {
if (this.tabIndex == this.tabList.length - 1) {
this.tabIndex = 0
} else {
this.tabIndex++
}
this.swiperIndex++
if (this.swiperIndex == this.swiperList.length-4) {
setTimeout(() => {
this.transition = 'unset'
this.swiperIndex = 0
}, 301);
setTimeout(() => {
this.transition = 'all 0.3s'
}, 360);
}
} else {
if (this.tabIndex == 0) {
this.tabIndex = this.tabList.length-1
} else {
this.tabIndex--
}
this.swiperIndex--
if (this.swiperIndex == -1) {
setTimeout(() => {
this.transition = 'unset'
this.swiperIndex = this.swiperList.length-5
}, 301);
setTimeout(() => {
this.transition = 'all 0.3s'
}, 360);
}
}
},
}
.swiper-box{
height: 6.88rem;
position: relative;
overflow: hidden;
margin-top: 0.5rem;
.swiper-list{
display: flex;
width: 9999rem;
height: 6.88rem;
overflow-x: auto;
position: absolute;
top: 0;
left: -9rem;
transition: all 0.3s;
.swiper-item{
display: flex;
align-content: center;
flex-wrap: wrap;
width: 12rem;
height: 6.88rem;
border-radius: 0.4rem;
margin-right: 0.4rem;
opacity: 0.6;
padding: 0 0.95rem;
&:last-child{
margin-right: 0;
}
&.active{
opacity: 1;
}
h3{
width: 100%;
font-size: 0.44rem;
font-weight: 600;
color: #fff;
}
p{
width: 4.13rem;
font-size: 0.18rem;
color: #fff;
margin-top: 0.4rem;
}
}
}
.prev-btn, .next-btn{
width: 0.8rem;
height: 0.8rem;
position: absolute;
left: 1rem;
top: 50%;
transform: translateY(-50%);
z-index: 9;
cursor: pointer;
img{
width: 100%;
height: 100%;
}
}
.next-btn{
left: unset;
right: 1rem;
}
}