一、div列表滾動

現在需要實現一個效果,內容無限、平滑、無閃動地向上滾動;當鼠標懸停到列表時,滾動暫停並高亮當前項;鼠標移出繼續滾動。這是在大屏項目中經常見到的一種展示數據的方式,本文為具體的實現方式。
實現原理:
在使用了js控制之後發現有閃動的現象,然後就換了種方式,我的想法是:把原始列表渲染兩次(A + A),用 CSS @keyframes 把整個雙倍內容從 translateY(0) 平滑移動到 translateY(-50%)(即移動一份內容的高度),動畫無限循環。因為下半部分是上半部分的複製,循環在視覺上是連續的、無斷點的——沒有 JS 在中間做“重置”,因此無閃動。話不多説直接上代碼
html:

<template>
  <div class="scroll-list" @mouseenter="pauseScroll" @mouseleave="resumeScroll">
    <div class="scroll-content" ref="scrollContent">
      <div
        v-for="item in typicalCaseList"
        :key="'a' + item.id"
        class="scroll-item"
      >
        <span>{{ item.text }}</span>
      </div>
      <!-- 複製一份 -->
      <div
        v-for="item in typicalCaseList"
        :key="'b' + item.id"
        class="scroll-item"
      >
        <span>{{ item.text }}</span>
      </div>
    </div>
  </div>
</template>

當上半段滾出視窗時,下半段的內容正好銜接上,使得動畫循環時不會出現斷裂。注意 key 的不同,避免 Vue 複用 DOM 導致複製失敗
js:

<script>
export default {
  data() {
    return {
      typicalCaseList: [
        // ... 你的數據
      ]
    };
  },
  mounted() {
    const list = this.$refs.scrollContent;
    // 根據列表長度動態設置動畫時長(可按需調整策略)
    const itemCount = this.typicalCaseList.length;
    const duration = Math.max(8, itemCount * 0.8); // 秒,示例:最少 8s
    list.style.setProperty('--duration', `${duration}s`);
  },
  methods: {
    pauseScroll() {
      this.$refs.scrollContent.style.animationPlayState = 'paused';
    },
    resumeScroll() {
      this.$refs.scrollContent.style.animationPlayState = 'running';
    }
  }
};
</script>

@mouseenter / @mouseleave 控制動畫的播放狀態,零延遲暫停/恢復
css:

<style scoped>
.scroll-list {
  height: 228px;
  margin: 0px 8px;
  overflow: hidden;
  position: relative;
}

.scroll-content {
  display: flex;
  flex-direction: column;
  animation: scroll-up var(--duration) linear infinite;
}

.scroll-item {
  height: 43px;
  font-size: 16px;
  color: #D0DEEE;
  padding: 0 10px;
  transition: all 0.3s;
  border-bottom: 1px dashed rgba(69,174,253,0.43);
  display: flex;
  flex-direction: row;
  align-items: center;
}

.scroll-item:hover {
  color: #03A7FA;
}

/* 真正無縫滾動動畫 */
@keyframes scroll-up {
  0% {
    transform: translateY(0);
  }
  100% {
    transform: translateY(-50%);
  }
}
</style>

translateY(-50%):把整個容器往上移 50%(即整份內容的一半),正好把第一份內容滾出,顯示第二份(與第一份相同),循環接着第一份。他之所以能解決閃爍的原因是因為動畫是連續的無限循環,瀏覽器合成層平滑過渡,動畫結束後 CSS 自動從 0% 開始新一輪,但因為畫面內容與起始狀態一致,用户看不到跳變(沒有 JS 重置 scrollTop 的那一幀)
拓展:
還可以根據需求進行一些部分的拓展,比如

  • 動態速度或者是時長更精確的計算
    通過計算單個.scroll-item的高度,計算原始列表總高度來獲取更準確的值
const itemHeight = this.$refs.scrollContent.querySelector('.scroll-item').offsetHeight;
const H = itemHeight * this.typicalCaseList.length;
const speed = 30; // px/s
const duration = H / speed;
this.$refs.scrollContent.style.setProperty('--duration', `${duration}s`);
  • 只在數據高度超出容器時啓用滾動
    如果列表很短(內容總高度 <= 你設定的總高度),不需要滾動。判斷邏輯:
if (content.scrollHeight <= container.clientHeight) {
  // 不啓用動畫:移除 animation
  content.style.animation = 'none';
} else {
  content.style.animation = `scroll-up var(--duration) linear infinite`;
}

二、table表格滾動

table表格的滾動主要是實現思路為複製一個表格內容,讓其形成無縫滾動的感覺,結合css實現效果

<div class="table-scroll-wrapper">
  <table class="table-box-right">
    <thead>
      <tr>
        <th>姓名</th>
        <th>城市</th>
        <th>年齡</th>
      </tr>
    </thead>
  </table>

  <div class="table-body-wrapper">
    <table class="table-box-right scroll-content">
      <!-- 可以通過判斷來實現達到多少條數據時,觸發滾動動畫 -->
      <tbody :class="{ scrollable: tableData.length > 5 }">
        <!-- 克隆兩次實現無縫滾動 -->
        <tr v-for="item in tableData" :key="item.f_id">
          <td>{{ item.name }}</td>
          <td>{{ item.city }}</td>
          <td>{{ item.age }}</td>
        </tr>
        <tr v-for="item in tableData" :key="'clone-' + item.f_id">
          <td>{{ item.name }}</td>
          <td>{{ item.city }}</td>
          <td>{{ item.age }}</td>
        </tr>
      </tbody>
    </table>
  </div>
</div>

css部分實現滾動

.table-scroll-wrapper {
    width: 100%;
    color: #fff;
    padding: 20px;
}

.table-box-right {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
}

.table-box-right th,
.table-box-right td {
    border: 1px solid #0058af;
    text-align: center;
    padding: 6px 8px;
    font-size: 14px;
}

/* 固定表頭 */
.table-box-right thead th {
    background: #103e5f;
    position: sticky;
    top: 0;
    z-index: 2;
    color: #37eef4;
}
.table-box-right td {
    background: #01204c;
}

/* 滾動容器 */
.table-body-wrapper {
    max-height: 200px;
    overflow: hidden;
    position: relative;
}

.scroll-content tr {
    display: table; /* 保持表格樣式 */
    width: 100%;
    table-layout: fixed;
}

@keyframes scrollUp {
    0% { transform: translateY(0); }
    100% { transform: translateY(-50%); } /* 移動一半,實現無縫滾動 */
}

.scroll-content tbody.scrollable {
    display: block; 
    animation: scrollUp 15s linear infinite; // 控制滾動速度 數值越大滾動越慢
}

.table-body-wrapper:hover .scroll-content tbody.scrollable {
    animation-play-state: paused;
}

/* 小於X條的 tbody 不加動畫,默認不滾動 */
.scroll-content tbody:not(.scrollable) {
    display: table-row-group; /* 保持正常表格佈局 */
    animation: none;
}

上述是通過純css樣式控制當數據大於你規定的條數時,表格開始滾動,鼠標劃入停止動畫,離開繼續動畫,控制css屬性這樣就能簡單的實現無縫滾動效果