遇到一个问题,在一个自适应页面中做跑马灯,因为内容高度有差异,如果采用常规的v-if 显示对应的卡片,那么跑马灯的高度会在切换过程中发生变化,所以将内容横排,使用scroll的方式,滚动卡片,这样整个卡片的高度就以内容最多的卡片为准了。
具体实现:
跑马灯组件的template如下所示,上半部分为内容展示,下半部分为切换按钮,当鼠标进入的时候卡片悬停,鼠标离开时卡片继续切换。展示内容由父组件传入。
<template>
<div class="carousel">
<div class="list" ref="list" @mouseenter="stop()" @mouseleave="setTimer()">
<div v-for="(item, index) in listData" class="card" :key="index">
<div :class="{'active': index===currentIndex,'unactive': index!==currentIndex}">
<slot :list="item" name="item"></slot>
</div>
</div>
</div>
<div class="change">
<div
class="item"
:class="{'active': currentIndex ===index }"
v-for="(list, index) in listData"
:key="index"
@click="jumpTo(index)"
></div>
</div>
</div>
</template>
listdata通过props传入;
props: ["listData"],
在也页面渲染完毕后设置timer,控制页面滚动,在页面destoryed的时候切记要销毁timer。
mounted() {
this.timer = setInterval(this.start, 2500);
},
destroyed() {
clearInterval(this.timer);
}
在方法中定义start,通过isHover字段是否停止切换,控制控制页面的切换过程,通过ref取得每张卡片在整个滚动页面的位置,通过设置页面滚动到特定位置实现卡片的切换,即成跑马灯。
methods: {
start() {
if (this.isHover) {
//鼠标悬浮的时候停止切换
return;
}
if (this.currentIndex === this.listData.length - 1) {
// 判断是否到达最后一个卡片,到最后一个后切换到第一个
this.jumpTo(0);
} else {
// 不在最后一个卡片的话,就顺序切换
this.jumpTo(++this.currentIndex);
}
},
setTimer() {
// 鼠标离开
this.isHover = false;
},
stop() {
// 鼠标悬停
this.isHover = true;
},
setCardPosition() {
// 横向滚动页面, 每个页面等宽,所以滚动宽度直接用 当前index*每个卡片宽度
this.$refs.list.scrollLeft =
this.$refs.list.clientWidth * this.currentIndex;
},
jumpTo(index) {
// 通过currentIndex控制按钮的active状态
this.currentIndex = index;
this.setCardPosition();
}
},
附上css:
<style scoped>
.carousel {
.list {
width: 100%;
display: flex;
overflow: hidden;
.card {
min-width: 100%;
position: relative;
cursor: pointer;
}
.active {
position: relative;
transition: left ease-in 0.5s;//设置动画效果
left: 0;
}
.unactive {
position: relative;
left: 100%;
opacity: 0;
}
}
.change {
display: flex;
justify-content: center;
margin-top: 30px;
.item {
width: 10px;
height: 10px;
cursor: pointer;
border-radius: 50%;
background-color: #e6e6e6;
&:nth-last-of-type(n + 2) {
margin-right: 14px;
}
&.active {
background-color: #60c25b;
}
}
}
}
</style>