VUE:Ul列表内容自动向上滚动

Ul列表背景图片:外部容器

Ul列表背景图片:头部

Ul列表背景图片:人员背景

1.每隔3秒,容器内的元素滚动一次。

2.鼠标移入移出事件:移入时,元素停止滚动。

tips: 不需要背景图将 background 相关删除就行

html 复制代码
<template>
  <div class="container">
    <div class="layout-right">
      <div class="border-box mb">
        <div class="border-title box-1_title">应急机构人员</div>
        <div class="border-container">
          <div class="view">
            <div class="view-button">查看</div>
          </div>

          <div
            class="scrollbar"
            ref="scrollbarRef"
            @mouseenter="onMouseEnter"
            @mouseleave="onMouseLeave">
            <div class="info-list">
              <ul>
                <li
                  v-for="(item, index) in visibleList"
                  :class="{ 'no-animation': index === 0 }"
                  :key="`${item}`">
                  {{ item }}
                </li>
              </ul>
            </div>
            <!-- 底部渐变遮罩,提示可滚动 -->
            <div v-if="emergencyList.length > 5" class="scroll-mask-bottom"></div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
js 复制代码
<script setup lang="ts">
  import { onMounted, onUnmounted, ref } from "vue";
  const scrollbarRef = ref(null);

  // 应急机构人员列表数据
  const emergencyList = ref([
    "自然灾害-环境监测组------刘 洋(15775692743)",
    "自然灾害-应急处置组------李伟刚(1234567899)",
    "自然灾害-通讯应急保障组------张海涛(1242532553)",
    "自然灾害-物资保障组------高 鹏(6666663314)",
    "自然灾害-救援队------赵 鹏(6666663314)",
    "自然灾害-安全警戒疏散组------张志远(6666663314)",
    "自然灾害-应急处置组------李伟刚(1234567899)",
    "自然灾害-通讯应急保障组------张海涛(1242532553)",
    "自然灾害-物资保障组------高 鹏(6666663314)",
    "自然灾害-救援队------赵 鹏(6666663314)",
    "自然灾害-安全警戒疏散组------张志远(6666663314)",
  ]);

  const visibleList = ref([...emergencyList.value.slice(0, 5)]);
  let timer: number | null = null;
  let isPaused = false;
  let currentIndex = 0;

  // 滚动列表 - 使用平滑滚动方式
  const scrollList = () => {
    if (isPaused) return;

    currentIndex = (currentIndex + 1) % emergencyList.value.length;
    const nextItems = [];
    for (let i = 0; i < 5; i++) {
      const index = (currentIndex + i) % emergencyList.value.length;
      nextItems.push(emergencyList.value[index]);
    }

    // 直接更新为新数据,通过 CSS 类控制第一条不显示动画
    visibleList.value = nextItems;
  };

  // 鼠标移入暂停滚动
  const onMouseEnter = () => {
    isPaused = true;
  };

  // 鼠标移出恢复滚动
  const onMouseLeave = () => {
    isPaused = false;
  };

  onMounted(() => {
    // 仅当数据超过5条时才启动自动滚动定时器(每隔3秒滚动一次)
    if (emergencyList.value.length > 5) {
      timer = window.setInterval(() => {
        scrollList();
      }, 3000);
    }
  });

  // 组件卸载时清除定时器
  onUnmounted(() => {
    if (timer) {
      clearInterval(timer);
      timer = null;
    }
  });
</script>
css 复制代码
<style scoped lang="scss">
  $app-header-height: 70px;

  .border-box {
    position: relative;
    z-index: 999;
    width: 424px;
    min-height: 160px;
    background-image: url("../assets/images/box.png");
    background-repeat: no-repeat;
    background-size: 100% 100%;
    background-color: #cacaca;
  }
  .border-title {
    background-image: url("../assets/images/box-header.png");
    background-repeat: no-repeat;
    background-size: 100% 100%;
  }

  .box-1_title {
    height: 36px;
    line-height: 37px;
    padding-left: 24px;
    color: #fff;
    font-size: 16px;
  }

  .border-container {
    padding-left: 1.25rem;
    padding-right: 1.25rem;
  }

  .view {
    padding-top: 1rem;
    padding-bottom: 0.25rem;
    .view-button {
      font-size: 14px;
      color: #35dbff;
      border-bottom: 1px solid #35dbff;
      width: 30px;
      text-align: center;
      position: absolute;
      right: 16px;
      top: 42px;
      padding-bottom: 1px;
      cursor: pointer;
    }
  }

  .mb {
    margin-bottom: 0.875rem;
  }

  .layout-right {
    position: absolute;
    left: 16px;
    top: calc($app-header-height + 14px);
    min-width: 200px;
    height: calc(100% - $app-header-height);
    z-index: 99;
    .scrollbar {
      position: relative;
      z-index: 999;
      width: 100%;
      height: 230px;
      padding: 8px 3px;
      margin-top: 14px;
      font-size: 14px;
      overflow: hidden;

      background-image: url("../../assets/images/应急机构人员背景.png");
      background-repeat: no-repeat;
      background-size: 100% 100%;

      .info-list {
        height: 100%;
        overflow: hidden;

        ul {
          margin: 0;
          padding: 0;
        }

        li {
          list-style: none;
          padding: 8px 10px;
          margin-bottom: 12px;
          background: linear-gradient(
            90deg,
            rgba(255, 255, 255, 0.1),
            rgba(255, 255, 255, 0.05)
          );
          border-left: 3px solid #35dbff;
          color: #ffffff;
          font-size: 13px;
          line-height: 1.4;
          cursor: pointer;
          transition: all 0.3s ease;
          
          // 使用等宽字体,解决数字显示不对齐问题
          font-family: 'Courier New', Courier, monospace;

          // 第一条信息不应用动画,直接隐藏
          &.no-animation {
            transition: none !important;
            animation: none !important;
          }

          &:hover {
            background: linear-gradient(
              90deg,
              rgba(53, 219, 255, 0.2),
              rgba(53, 219, 255, 0.1)
            );
            border-left-color: #ffc002;
            transform: translateX(5px);
          }
        }
      }

      // 底部渐变遮罩
      .scroll-mask-bottom {
        position: absolute;
        bottom: 0;
        left: 0;
        right: 0;
        height: 30px;
        background: linear-gradient(to bottom, transparent, rgba(0, 42, 64, 0.5));
        pointer-events: none;
      }
    }

    // 列表滚动动画 - 只对非第一条应用动画
    .info-list {
      ul {
        position: relative;
      }

      li {
        will-change: transform, opacity;
        backface-visibility: hidden;
        -webkit-backface-visibility: hidden;
        transform: translateZ(0);
        -webkit-transform: translateZ(0);
      }
    }

    // 列表项优化,避免残影
    .info-list {
      ul {
        position: relative;
      }

      li {
        will-change: transform, opacity;
        backface-visibility: hidden;
        -webkit-backface-visibility: hidden;
        transform: translateZ(0);
        -webkit-transform: translateZ(0);
      }
    }
  }
</style>
相关推荐
web小白成长日记9 小时前
CSS 作用域隔离实战:React、Vue 与 Styled Components 的三种范式
前端·css·vue.js·react.js
天意pt1 天前
Blog-SSR 系统操作手册(v1.0.0)
前端·vue.js·redis·mysql·docker·node.js·express
清风ai明月1 天前
在vue3中Promise是什么
vue.js
毕设源码-邱学长1 天前
【开题答辩全过程】以 基于VUE的打车系统的设计与实现为例,包含答辩的问题和答案
前端·javascript·vue.js
麦麦大数据1 天前
J009 美食推荐可视化大数据系统vue+springboot
vue.js·spring boot·mysql·推荐算法·美食·可视化分析·沙箱支付
rfidunion1 天前
springboot+VUE+部署(1。新建项目)
java·vue.js·spring boot
Irene19911 天前
在 Vue 中使用 TypeScript 的几种方式
vue.js·typescript
唯情于酒1 天前
Docker部署若依(前后端分离版)
vue.js·docker·容器
hhcccchh1 天前
学习vue第八天 Vue3 模板语法和内置指令 - 简单入门
前端·vue.js·学习