需求如下:给普通轮播图下面增加速度轮播点
代码场景使用elm的弹窗弹的轮播图,然后配合elm的走马灯,核心代码就是openAnimation一个方法而已,仅供大家参考,若有更简洁点的方法欢迎评论区共同探讨
<template>
<div class="dialog">
<el-dialog
:append-to-body="true"
:close-on-click-modal="false"
:modal-append-to-body="true"
:visible.sync="dialogVisible"
:show-close="false"
width="560px"
>
<div class="content">
<div class="close" @click="close">
<img src="../images/icon_close.png" alt="" />
</div>
<el-carousel
indicator-position="none"
arrow="never"
@change="changeActive"
height="406px"
:interval="interval"
ref="carousel"
>
<el-carousel-item
v-for="item in imageList"
:key="item.id"
@click.native="goSign"
>
<img class="myimg" :src="item.webCoverImgUrl" alt="" />
<!-- webCoverImgUrl -->
</el-carousel-item>
</el-carousel>
<!-- 自定义指示器 -->
<div class="list" v-if="imageList.length > 1">
<div
class="indicator"
v-for="(item, index) in imageList"
:key="item.id"
@mouseenter="toChangeActive(index)"
>
<div
class="active"
ref="active"
:style="{ transform: `translateX(${-(targetWidth - width)}px)` }"
v-show="index === currentIdx"
></div>
</div>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
data () {
return {
companyName: '',
type: 0,
params: {},
activityList: [],
currentIdx: 0,
// raf控制的width
width: 0,
// 目标width,要跟轮播点width保持一致
targetWidth: 136,
interval: 3000
}
},
props: {
dialogVisible: {
type: Boolean,
default: true
},
imageList: {
type: Array,
defaule: () => {
return []
}
}
},
mounted () {},
watch: {
imageList: {
immediate: true,
handler (newValue, oldValue) {
if (newValue.length > 1) {
this.changeActive(0)
}
}
}
},
methods: {
toChangeActive (idx) {
this.$refs.carousel.setActiveItem(idx)
},
changeActive (val) {
if(this.imageList.length<=1) return
this.currentIdx = val
this.openAnimation()
},
openAnimation () {
// console.log('准备开启动画');
window.cancelAnimationFrame(this.handle)
this.initailTimer = 0
this.preTimer = 0
this.useTimer = 0
this.width = 0
const fn = timer => {
!this.initailTimer && (this.initailTimer = timer)
// 判断当时所用的时间与初始时间之差
// 重复调用这个,他会在下一次显示器刷新时执行回调,
this.useTimer = timer - this.initailTimer
// 两次运行间隔浪费了多少时间,就决定下一次渲染要加多少,保持匀速
this.preTimer &&
(this.width +=
(this.targetWidth / this.interval) * (timer - this.preTimer))
this.preTimer = timer
// console.log(this.width, timer)
if (this.useTimer >= this.interval) {
console.log('动画时间到达')
// window.cancelAnimationFrame(this.handle)
} else {
// 继续做动画
window.requestAnimationFrame(fn)
}
}
this.handle = window.requestAnimationFrame(fn)
},
close () {
this.$emit('changeDialogVisible', false)
},
goSign () {
this.$emit('openDialog')
this.$emit('changeDialogVisible', false)
}
},
destroyed () {
window.cancelAnimationFrame(this.handle)
},
components: {}
}
</script>
<style lang="scss" scoped>
/deep/ .el-dialog {
border-radius: 8px;
background-color: transparent;
}
/deep/ .el-dialog__body {
padding: 0;
}
/deep/ .el-dialog__header {
display: none;
}
.content {
height: 380px;
width: 100%;
cursor: pointer;
position: relative;
.close {
width: 20px;
height: 20px;
// background: #155882;
// border: 1px dashed rgba(16, 139, 177, 0.4);
// border-radius: 31px;
// position: absolute;
// top: -8px;
// right: -7px;
// text-align: center;
// color: #108bb1;
// line-height: 16px;
// cursor: pointer;
// z-index: 999;
position: absolute;
top: -8px;
right: -7px;
z-index: 999;
cursor: pointer;
> img {
width: 100%;
height: 100%;
}
}
/deep/ .el-carousel__item {
display: flex;
// align-items: center;
justify-content: center;
}
img {
// width: 100%;
max-width: 560px;
max-height: 370px;
// height: 100%;
}
// /deep/ .el-carousel__indicators {
// // transform: translate(-50%,100px);
// }
}
.list {
position: absolute;
bottom: -16px;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
z-index: 999;
.indicator {
// width: 68px;
// height: 6px;
width: 136px;
height: 12px;
margin: 0 -18px;
background: rgba(255, 255, 255, 0.2);
border-radius: 6px;
overflow: hidden;
// 为了动画更流畅
transform: scale(0.5);
.active {
width: 136px;
transform: translateX(-100%);
height: 100%;
background-color: #fff;
}
}
// margin-top: 380px;
}
// .block {
// width: 0;
// height: 0;
// border-top: 30px solid skyblue;
// border-right: 30px solid transparent;
// border-left: 30px solid transparent;
// }
</style>