参考了uniapp插件市场的头像轮播实现,在其基础上优化了实现效果
<template>
<view class="avatar-banner" :style="[boxBaseSyle()]">
<image
v-for="(avatar, index) in list"
:key="avatar.id"
:src="avatar.url"
class="absolute"
:style="[itemBaseSyle(), itemSyle(index, avatar)]"
>
</image>
</view>
</template>
<script>
export default {
name: "AvatarBanner",
props: {
urls: {
type: Array,
default: () => {
return [];
},
},
interval: {
type: Number,
default: 1500,
desc: "轮播间隔时间",
},
width: {
type: Number,
default: 40,
},
height: {
type: Number,
default: 40,
},
overlap: {
type: Number,
default: 20,
desc: "重叠的部分",
},
showNumber: {
type: Number,
default: 5,
desc: "展示数量,实际展示少一个",
},
},
data() {
return {
imageUrls: [
`./static/image/insurance/term2/avatar-1@2x.png`,
`./static/image/insurance/term2/avatar-2@2x.png`,
`./static/image/insurance/term2/avatar-3@2x.png`,
`./static/image/insurance/term2/avatar-4@2x.png`,
`./static/image/insurance/term2/avatar-5@2x.png`,
`./static/image/insurance/term2/avatar-6@2x.png`,
`./static/image/insurance/term2/avatar-7@2x.png`,
`./static/image/insurance/term2/avatar-8@2x.png`,
`./static/image/insurance/term2/avatar-9@2x.png`,
`./static/image/insurance/term2/avatar-10@2x.png`,
`./static/image/insurance/term2/avatar-11@2x.png`,
],
list: [],
tempList: [],
intervalTimer: null,
curLastIndex: 0,
};
},
computed: {
marginLeft() {
return this.width - this.overlap;
},
},
watch: {},
mounted() {
this.stop();
this.handleUrls();
},
beforeDestroy() {
this.stop();
},
onUnload() {
this.stop();
},
methods: {
handleUrls(val = []) {
const defaultList = this.imageUrls;
const urls = !val || !val.length ? defaultList : val;
this.tempList = urls;
const length = urls.length;
const len = this.showNumber > length ? length : this.showNumber;
const tempList = urls.slice(0, len).map((item, index) => {
const url = item;
const order = index + 1;
return {
url,
order: order,
id: `avatar-${order}`,
};
});
this.list = tempList;
this.curLastIndex = this.showNumber;
this.start();
},
itemSyle(index, item) {
const total = this.list.length;
const left = this.marginLeft;
const style = {
"z-index": Math.abs(item.order - total),
transition: `${this.interval / 1000}s`,
transform: `translateX(-${
(item.order - 1) * left
}rpx) scale(1)`,
};
// 缩小中
if (item.order == 0) {
style.transform = `translateX(0) scale(0)`;
}
// 位移中 移动到末尾
if (item.order == this.showNumber) {
style.transform = ` translateX(0) scale(0)`;
}
// 进行缩放和位移状态的改变
this.nextState(item);
return style;
},
// 进行缩放和位移 状态 的改变 不具体执行缩放
nextState(item) {
const total = this.list.length;
if (item.order == 0) {
const timer = setTimeout(() => {
// 300 后缩放结束 开始移动到末尾
item.order = total;
clearTimeout(timer);
}, 250);
}
},
itemBaseSyle() {
return { width: this.width + "rpx", height: this.height + "rpx" };
},
boxBaseSyle() {
const len = this.list.length;
return {
width: len * this.width - (len - 1) * this.overlap + "rpx",
height: this.height + "rpx",
marginLeft: "-" + this.overlap + "rpx",
};
},
start() {
this.intervalTimer = setInterval(() => {
this.forwardMove();
}, this.interval); // 可以根据需要调整间隔时间
},
stop() {
clearInterval(this.intervalTimer);
this.intervalTimer = null;
},
/**
* 向前移动
*/
forwardMove() {
// 第一条数据
this.list.forEach((item, index) => {
// 最后一条数据
if (item.order == 1) {
setTimeout(() => {
item.url = this.tempList[this.curLastIndex];
}, 500);
}
item.order--;
});
if (this.curLastIndex === this.tempList.length - 1) {
this.curLastIndex = 1;
} else {
this.curLastIndex++;
}
},
},
};
</script>
<style lang="scss" scoped>
.avatar-banner {
overflow: hidden;
width: 100%;
position: relative;
}
.absolute {
position: absolute;
border-radius: 50%;
right: 0;
}
</style>
由于要动态替换图片进行轮播,动画效果使用css和js的定时器效果实现 目前存在问题:手机端页面切入后台,由于使用了定时器效果,切回来的时候轮播动画加速了