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>
相关推荐
方也_arkling19 分钟前
elementPlus按需导入配置
前端·javascript·vue.js
David凉宸41 分钟前
vue2与vue3的差异在哪里?
前端·javascript·vue.js
css趣多多1 小时前
this.$watch
前端·javascript·vue.js
有来技术2 小时前
ASP.NET Core 权限管理系统(RBAC)设计与实现|vue3-element-admin .NET 后端
vue.js·后端·c#·asp.net·.net
qq_12498707532 小时前
基于springboot的林业资源管理系统设计与实现(源码+论文+部署+安装)
java·vue.js·spring boot·后端·spring·毕业设计·计算机毕业设计
qq_12498707533 小时前
基于springboot的竞赛团队组建与管理系统的设计与实现(源码+论文+部署+安装)
java·vue.js·spring boot·后端·信息可视化·毕业设计·计算机毕业设计
可问春风_ren3 小时前
Vue3 入门详解:从基础到实战
开发语言·前端·javascript·vue.js·前端框架·ecmascript·edge浏览器
想睡好3 小时前
ref和reactive
前端·javascript·vue.js
毕设十刻3 小时前
基于Vue的餐厅收银系统s6150(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末
前端·数据库·vue.js
xkxnq4 小时前
第四阶段:Vue 进阶与生态整合(第 58 天)(Vue 项目部署:打包、上线与服务器配置)
服务器·前端·vue.js