实现思路:卡片移动使用css的translateY属性实现,每个卡片从最下面移动到最上面,然后直接移动到最下面,每次改变的位移是固定的,假设每次移动50px,当移动到最小时,就让translataY为0,但是一定要进行初始化每个div的初始位置;
代码:
<template>
<div id="demo">
<div class="box">
<!-- 左下角预警 -->
<div
class="warning"
:ref="setItemRef"
:style="{
transform: `translateY(${-index * 50}px)`,
transition: 'transform 0.9s ease',
zIndex: `${-index + 100}`
}"
v-for="(item, index) in warningInfoList"
>
<div class="warning-title">{
{ item.warning_type }}</div>
<div class="warning-content" :style="{display: index != 0 ?'none':'block'}">
<div class="warning-time">{
{ item.time }}</div>
<div class="warning-word">{
{ item.warning_content }}</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { reactive, ref, computed, onMounted, onUnmounted, nextTick } from 'vue'
// let warningInfoList = ref([
// { warning_type: '台风', warning_content: '大风,注意安全', time: '12日-13' },
// { warning_type: '暴雨', warning_content: '暴雨,注意安全', time: '12日-13' },
// { warning_type: '冰雹', warning_content: '冰雹,注意安全', time: '12日-13' }
// ])
import {warningInfo} from '@renderer/api/index.ts';
//预警数据
let warningInfoList = ref([])
const getWarningInfo = async () => {
let response = await warningInfo({})
warningInfoList.value = response.data.ret.results
let maxLength = warningInfoList.value.length
nextTick(() => {
setInterval(() => {
warningInfoList.value.forEach((item, index) => {
let aTransformY = parseInt(itemRefs[index].style.transform.substring(11))
let bIndex = itemRefs[index].style.zIndex
// console.log("aTransformY",aTransformY);
if (aTransformY == -((maxLength - 1) * 50)) {
aTransformY = 0
itemRefs[index].children[1].style.display = 'block'
} else {
aTransformY -= 50
itemRefs[index].children[1].style.display = 'none'
}
if(bIndex == (100 - maxLength+1)){
bIndex = 100
}else {
bIndex -= 1
}
itemRefs[index].style.transform = `translateY(${aTransformY}px)`
itemRefs[index].style.zIndex = bIndex
// console.log('itemRefs[index]', itemRefs[index].style)
})
}, 3000)
})
}
const itemRefs = []
const setItemRef = (el) => {
if (el) {
itemRefs.push(el)
}
}
// console.log("itemRefs",itemRefs);
onMounted(async () => {
await getWarningInfo()
//初始化
// nextTick(() => {
// setInterval(() => {
// warningInfoList.value.forEach((item, index) => {
// let aTransformY = parseInt(itemRefs[index].style.transform.substring(11))
// let bIndex = itemRefs[index].style.zIndex
// console.log("aTransformY",aTransformY);
// // debugger
// if (aTransformY == -((maxLength - 1) * 50)) {
// aTransformY = 0
// itemRefs[index].children[1].style.display = 'block'
// } else {
// aTransformY -= 50
// itemRefs[index].children[1].style.display = 'none'
// }
// if(bIndex == (100 - maxLength+1)){
// bIndex = 100
// }else {
// bIndex -= 1
// }
// itemRefs[index].style.transform = `translateY(${aTransformY}px)`
// itemRefs[index].style.zIndex = bIndex
// // console.log('itemRefs[index]', itemRefs[index].style)
// })
// }, 3000)
// })
})
</script>
<style lang="less" scoped>
#demo {
position: absolute;
left: 40px;
bottom: 30px;
.box {
width: 301px;
height: 360px;
// overflow: scroll;
position: relative;
.warning {
width: 301px;
height: 280px;
position: absolute;
.warning-title {
height: 40px;
background-image: url('../assets/img/title_bg.png');
font-size: 18px;
font-family:
PingFang SC,
PingFang SC-700;
font-weight: 700;
color: #ff6838;
line-height: 40px;
padding-left: 60px;
}
.warning-content {
height: 240px;
border-radius: 0px 0px 8px 8px;
padding-top: 20px;
box-sizing: border-box;
background: rgba(255, 245, 209, 0.9);
> .warning-time {
height: 30px;
font-size: 20px;
font-family:
PingFang SC,
PingFang SC-400;
font-weight: 500;
color: #009f80;
line-height: 30px;
padding-left: 20px;
box-sizing: border-box;
position: relative;
&::before {
display: block;
content: '';
width: 3px;
height: 3px;
border-radius: 50%;
background-color: #009f80;
position: absolute;
top: 50%;
left: 3%;
}
}
.warning-word {
padding: 20px 30px;
box-sizing: border-box;
font-size: 20px;
font-family:
PingFang SC,
PingFang SC-400;
font-weight: 400;
color: #313737;
line-height: 30px;
}
}
}
}
}
</style>
如何没有接口,可以使用里面的假数据先测试