vue+原生js+element-ui实现轮播列表动画(无限轮播)
效果展示实现思路用element-ui中的el-row和el-col来构建列表,若无element-ui,也可用类似布局组件或直接用div元素实现将滚动区域封装,使用绝对定位与相对定位的方式,并将超出滚动区域部分hidden隐藏下述业务代码有每分钟刷新一次列表的需求,所以用两个interval,若纯轮播则一个interval即可通过改变子元素相对于父元素的top值,并设置transition: a
·
效果展示
实现思路
- 用element-ui中的el-row和el-col来构建列表,若无element-ui,也可用类似布局组件或直接用div元素实现
- 将滚动区域封装,使用绝对定位与相对定位的方式,并将超出滚动区域部分hidden隐藏
- 下述业务代码有每分钟刷新一次列表的需求,所以用两个interval,若纯轮播则一个interval即可
- 通过改变子元素相对于父元素的top值,并设置
transition: all 1s;
即可出现如图所示效果 - 当轮播结束后再次首尾相连,即可实现无限轮播
关键代码
流畅过渡
.table {
position: absolute;
transition: all 1s;
}
js动画与无限轮播
startAnimation() {
let flag = 0;
if (this.isInterval) {
let top = 0;
if (this.$refs.table) {
this.$refs.table.style.top = top + "rem";
}
let tmp = JSON.parse(JSON.stringify(this.dataList));
this.tableInterval = setInterval(() => {
if (flag === this.step) {
this.dataList = this.dataList.concat(tmp);
flag = 0;
} else {
flag++;
}
top = top - 1.65;
if (this.$refs.table) {
this.$refs.table.style.top = top + "rem";
}
}, 3000);
}
实现代码(以实际使用为例)
<template>
<div class="situation-risk-event-e">
<qz-loading-animation v-if="isLoading"></qz-loading-animation>
<div class="situation-risk-event" v-if="!isLoading">
<div class="situation-risk-event__header">
<el-row>
<el-col :span="5"><span class="name">时间</span></el-col>
<el-col :span="3"><span class="name">风险等级</span></el-col>
<el-col :span="14"><span class="name">风险描述</span></el-col>
<el-col :span="2"><span class="name">操作</span></el-col>
</el-row>
</div>
<div class="situation-risk-event__content">
<div class="table" ref="table">
<el-row v-for="(row, index) in dataList" :key="index">
<el-col :span="5"
><span class="text">{{ row.time }}</span></el-col
>
<el-col :span="3">
<div :class="'level__' + row.level">
{{ levelMap[row.level] }}
</div></el-col
>
<el-col :span="14"
><div class="text">
<risk-desc
:overviewInfo="row.desc"
:mode="true"
></risk-desc></div
></el-col>
<el-col :span="2"
><qz-icon
class="icon-chakan-lv"
@click.native="
$linkTo({
path: PAGE_URL_EXCEPTION_DETAIL,
query: { type: row.policyId, riskId: row.riskInfoId },
type: '_blank',
})
"
></qz-icon
></el-col>
</el-row>
</div>
</div>
</div>
</div>
</template>
<script>
import { PAGE_URL_EXCEPTION_DETAIL } from "@/constant/page-url-constants"
import { getRiskEvent } from "@/service/situation-service"
import { handleRiskDesc } from "@/utils/risk-desc";
import RiskDesc from "@/pages/risk/packages/risk-desc.vue"
export default {
components: { RiskDesc },
data() {
return {
PAGE_URL_EXCEPTION_DETAIL,
isLoading: false,
isInterval: false,
getInterval: null,
tableInterval: null,
levelMap: {
1: "低",
2: "中",
3: "高"
},
dataList: [],
step: 0
}
},
mounted() {
this.$nextTick(() => {
this.init();
this.getInterval = setInterval(() => {
this.init();
}, 60000);
})
},
methods: {
// 初始化
async init() {
this.isLoading = true;
clearInterval(this.tableInterval);
this.tableInterval = null;
this.dataList = [];
await getRiskEvent().then(res => {
this.isInterval = res.data.length > 3 ? true : false;
this.step = res.data.length - 3;
res.data.forEach(item => {
this.dataList.push({
time: moment(item.firstTime).format('MM/DD HH:mm:ss'),
level: item.level,
desc: handleRiskDesc(false, item),
riskInfoId: item.riskInfoId,
policyId: item.policyId
})
});
}).catch(() => {
this.$message.error("获取风险事件数据失败")
});
this.isLoading = false;
this.startAnimation();
},
// 开始动画
startAnimation() {
let flag = 0;
if (this.isInterval) {
let top = 0;
if (this.$refs.table) {
this.$refs.table.style.top = top + "rem";
}
let tmp = JSON.parse(JSON.stringify(this.dataList));
this.tableInterval = setInterval(() => {
if (flag === this.step) {
this.dataList = this.dataList.concat(tmp);
flag = 0;
} else {
flag++;
}
top = top - 1.65;
if (this.$refs.table) {
this.$refs.table.style.top = top + "rem";
}
}, 3000);
}
}
},
destroyed() {
clearInterval(this.getInterval);
this.getInterval = null;
clearInterval(this.tableInterval);
this.tableInterval = null;
}
}
</script>
<style lang="less">
.level-style() {
height: 0.9rem;
width: 0.9rem;
color: #000000;
padding: 0 0.1rem;
text-align: center;
line-height: 1rem;
font-size: 0.5rem;
border-radius: 0.1rem;
font-weight: 500;
}
.situation-risk-event {
&-e {
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 100%;
padding: 2.25rem 1.3rem 1rem;
&__content {
position: relative;
height: 11vh;
overflow: hidden;
.table {
position: absolute;
transition: all 1s;
}
}
.el-row {
height: 1.65rem;
padding: 0.3rem 0;
border-bottom: 0.1rem solid #2b2f45;
}
&__header {
.name {
color: #fff;
font-size: 0.7rem;
}
}
i {
color: #50c3d1;
font-size: 0.7rem;
cursor: pointer;
}
.level {
&__1 {
.level-style();
background: #419f8a;
}
&__2 {
.level-style();
background: #f8c155;
}
&__3 {
.level-style();
background: #fa4f4d;
}
}
.text {
color: rgba(255, 255, 255, 0.6);
padding-right: 1rem;
font-size: 0.7rem;
}
}
</style>
更多推荐
已为社区贡献7条内容
所有评论(0)