文件下载:https://download.csdn.net/download/zluz_/86406404
作为components组件引入进来,使用:
<Scroll
v-if="peopleConfigData.length > 0"
:is-hover="true"
:list="peopleConfigData"
:time-space="3000"
:show-count="5"
:length="peopleConfigData.length"
:interval-time="2000"
class="table-item"
>
<div v-for="(i, index) in peopleConfigData" :key="index" class="flex-ac">
<div
style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 1%;"
>
<div class="info-name">{{ i.name }}</div>
<div>{{ i.value }}%</div>
</div>
<el-progress :percentage="i.value" :show-text="false" />
</div>
</Scroll>
<template>
<div
ref="banner"
:class="`banner ${className}`"
@mouseenter="mouseenterFunc"
@mouseleave="mouseleaveFunc"
>
<div ref="originDom" class="originDom">
<div
v-for="n in repeatTime"
ref="originDomItem"
:key="n"
class="originDomItem"
>
<slot />
</div>
</div>
</div>
</template>
<script>
export default {
props: {
// 是否反向
reverse: {
type: [Boolean],
default: function() {
return false
}
},
// 偏移的百分比
offsetPrecent: {
type: [Number],
default: function() {
return 10
}
},
// 滚动模式,单条或者整页,可选值为 item 或者 page
mode: {
type: [String],
default: function() {
return 'item'
}
},
// 动画的持续时间,ms为单位
transitionDuration: {
type: [Number],
default: function() {
return 500
}
},
// 单条动画之间的间隔时间
animationInterval: {
type: [Number],
default: function() {
return 100
}
},
// 轮播的间隔时间,ms为单位
intervalTime: {
type: [Number],
default: function() {
return 3000
}
},
// 显示的条数
showCount: {
type: [Number],
default: function() {
return 10
}
},
// 鼠标悬停的时候是否暂停
hoverPause: {
type: [Boolean],
default: function() {
return true
}
},
// 起始模糊程度
startBlur: {
type: [Number],
default: function() {
return 0
}
},
// 结束模糊程度
endBlur: {
type: [Number],
default: function() {
return (0 * window.innerHeight) / 1440
}
},
// 起始透明度
startOpacity: {
type: [Number],
default: function() {
return 1
}
},
// 结束透明度
endOpacity: {
type: [Number],
default: function() {
return 1
}
},
// 类名
className: {
type: [String],
default: function() {
return ''
}
},
// 是否使用复制模式,即传入的数据小于等于要显示的条数的时候,自动复制
repeat: {
type: [Boolean],
default: function() {
return false
}
}
},
data: function() {
return {
msg: 'banner',
enable: true,
childrenDom: [],
repeatTime: 1,
active: 0,
originLength: 0,
timer: 0,
alive: true
}
},
methods: {
mouseenterFunc() {
/* eslint-disable */
this.hoverPause && (this.enable = false);
},
mouseleaveFunc() {
/* eslint-disable */
this.hoverPause && (this.enable = true);
},
computeChildrenDom() {
return new Promise((resolve) => {
// console.log(this.$refs.originDomItem[0].children)
console.log(this.$refs.originDomItem[0].children.length)
if (this.$refs.originDomItem[0].children.length) {
let origin = [...this.$refs.originDomItem[0].children];
// console.log('origin', origin)
this.originLength = origin.length;
let repeatTime = 1;
if (!this.repeat && this.childrenDom.length < this.showCount) {
console.log();
} else {
while (repeatTime * this.originLength < this.showCount + 2) {
repeatTime = repeatTime + 1;
}
}
this.repeatTime = repeatTime;
this.childrenDom = [];
this.$nextTick(() => {
let list = [...this.$refs.originDomItem];
list.forEach((item) => {
[...item.children].forEach((dom) => {
dom.style.position = "absolute";
dom.style.transition = `all ${this.transitionDuration / 1000}s`;
dom.style.width = "100%";
dom.style.opacity = 1;
this.childrenDom.push(dom);
});
});
resolve();
});
}
});
},
computeContainerHeight() {
if (!this.childrenDom.length) {
return false;
}
let sum = 0;
for (let i = 0; i < this.showCount; i++) {
let index = (this.active + i) % this.childrenDom.length;
sum = sum + this.childrenDom[index].offsetHeight;
}
/* eslint-disable */
this.$refs.banner && (this.$refs.banner.style.height = `${sum}px`);
},
computeItemStyle() {
if (!this.childrenDom.length) {
return false;
}
if (!this.repeat && this.childrenDom.length < this.showCount + 1) {
let sum = 0;
this.childrenDom.forEach((item, index) => {
item.style.top = `${sum}px`;
item.style.left = 0;
item.style.opacity =
this.startOpacity +
((this.endOpacity - this.startOpacity) /
(this.childrenDom.length - 1)) *
index;
item.style.filter = `blur(${
this.startBlur +
((this.endBlur - this.startBlur) / (this.childrenDom.length - 1)) *
index
}px)`;
sum = sum + this.childrenDom[index].offsetHeight;
});
} else {
// 当使用非重复模式,并且 当前的数据数量 < 显示条数 + 1
let sum = 0;
let indexList = [];
let prevIndex =
(this.active + this.childrenDom.length - 1) % this.childrenDom.length;
let prev = this.childrenDom[prevIndex];
prev.style.top = 0;
prev.style[this.reverse ? "left" : "right"] = `${
(this.offsetPrecent / 100) * this.$refs.banner.offsetWidth
}px`;
prev.style.opacity = 0;
prev.style.pointerEvents = "none";
indexList.push(prevIndex);
for (let i = 0; i < this.showCount; i++) {
setTimeout(() => {
let index = (this.active + i) % this.childrenDom.length;
indexList.push(index);
this.childrenDom[index].style.top = `${sum}px`;
this.childrenDom[index].style[this.reverse ? "left" : "right"] = 0;
this.childrenDom[index].style.pointerEvents = "auto";
if (this.showCount > 1) {
// console.log(this.startOpacity + (this.endOpacity - this.startOpacity) / (this.showCount - 1) * i)
this.childrenDom[index].style.opacity =
this.startOpacity +
((this.endOpacity - this.startOpacity) / (this.showCount - 1)) *
i;
this.childrenDom[index].style.filter = `blur(${
this.startBlur +
((this.endBlur - this.startBlur) / (this.showCount - 1)) * i
}px)`;
} else {
console.log(this.startOpacity);
this.childrenDom[index].style.opacity = this.startOpacity;
this.childrenDom[
index
].style.filter = `blur(${this.startBlur}px)`;
}
sum = sum + this.childrenDom[index].offsetHeight;
}, this.animationInterval * (i + 1));
}
setTimeout(() => {
for (let i = 0; i < this.childrenDom.length; i++) {
if (indexList.indexOf(i) < 0) {
this.childrenDom[i].style[this.reverse ? "left" : "right"] = 0;
this.childrenDom[i].style.top = `${sum}px`;
this.childrenDom[i].style.opacity = 0;
this.childrenDom[i].style.pointerEvents = "none";
}
}
}, this.showCount * this.animationInterval);
}
},
animationFrame() {
window.requestAnimationFrame(() => {
if (this.enable) {
this.timer = this.timer + 1000 / 60;
if (this.timer > this.intervalTime) {
this.timer = 0;
this.active = (this.active + 1) % this.childrenDom.length;
this.$emit("changeActive", this.active % this.originLength);
this.computeContainerHeight();
this.computeItemStyle();
}
}
/* eslint-disable */
this.alive && this.animationFrame();
});
},
init() {
setTimeout(() => {
this.computeChildrenDom().then(() => {
this.computeContainerHeight();
this.computeItemStyle();
});
}, 0);
},
},
mounted() {
this.alive = true;
/* eslint-disable */
this.intervalTime !== 0 && this.animationFrame();
this.init()
},
watch: {
// activeIndex: function (newVal) {
// this.$emit('changeActive', (newVal + 1) % this.children.length)
// }
},
beforeUpdate() {},
beforeDestroy() {
this.alive = false;
},
};
</script>
<style lang="scss" scoped>
.banner {
position: relative;
overflow: visible;
.originDom {
.originDomItem {
> * {
opacity: 0;
}
}
}
}
</style>