vue3 writes vertical carousel effect (translateY)

Implementation idea: Card movement is implemented using the translateY attribute of CSS. Each card moves from the bottom to the top, and then moves directly to the bottom. The displacement of each change is fixed. Assume that each movement is 50px. When it moves to the minimum , let translataY be 0, but the initial position of each div must be initialized;

Code:

<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>

If there is no interface, you can use the fake data inside to test first

Guess you like

Origin blog.csdn.net/weixin_51747462/article/details/133011611