SeamlessScroll 组件介绍
功能说明
SeamlessScroll 是一个实现无缝滚动效果的 Vue 3 组件,主要功能包括:
- 无缝垂直滚动:支持向上或向下无缝滚动内容
 - 可控制滚动速度 :通过 
speed属性调整滚动速度 - 可控制滚动方向 :通过 
direction属性设置向上('up')或向下('down')滚动 - 鼠标悬停暂停:鼠标悬停时自动暂停滚动,移开后继续
 - 动态内容同步:自动同步两个滚动容器的内容,确保无缝衔接
 - 重置功能 :提供 reset 方法可重置滚动位置
 
组件源码
            
            
              js
              
              
            
          
          <script setup>
  import { onBeforeUnmount, onMounted, ref } from 'vue'
  
  const props = defineProps({
    speed: {
      type   : Number,
      default: 1000
    },
    direction: {
      type   : String,
      default: 'up'
    }
  })
  
  const box = ref(null)
  const refRoll1 = ref(null)
  const refRoll2 = ref(null)
  let top = 0
  let height = 0
  let shadowHeight = 0
  const sp = props.speed / 1000
  let end = false
  let isMouseHover = false
  
  /**
   * 刷新滚动内容的位置和高度
   * 通过比较两个滚动元素的高度来同步内容
   */
  function refresh () {
    height = refRoll1.value.clientHeight
    shadowHeight = refRoll2.value.clientHeight
  
    if (shadowHeight !== height) {
      refRoll2.value.innerHTML = refRoll1.value.innerHTML
    }
    if (top < 0) {
      if (Math.abs(top) >= height) {
        const tmp = refRoll1.value
        refRoll1.value = refRoll2.value
        refRoll2.value = tmp
        top = 0
      }
      refRoll1.value.style.transform = `translate3d(0,${top}px,0)`
      refRoll2.value.style.transform = `translate3d(0,${height + top}px,0)`
    } else {
      if (Math.abs(top) >= height) {
        const tmp = refRoll1.value
        refRoll1.value = refRoll2.value
        refRoll2.value = tmp
        top = -height
      }
      refRoll1.value.style.transform = `translate3d(0,${top}px,0)`
      refRoll2.value.style.transform = `translate3d(0,${top - height}px,0)`
    }
  }
  
  /**
   * 执行动画帧函数,实现无缝滚动效果
   * 使用requestAnimationFrame来优化动画性能
   */
  function doAnimationFrame () {
    requestAnimationFrame(() => {
      if (end) {
        return
      }
  
      // 鼠标悬停时暂停滚动
      if (isMouseHover) {
        refresh()
        doAnimationFrame()
        return
      }
  
      // 根据容器高度和方向控制滚动
      if (height > box.value.clientHeight) {
        if (props.direction === 'down') {
          top += sp
        }
        if (props.direction === 'up') {
          top -= sp
        }
      } else {
        top = 0
      }
      refresh()
      doAnimationFrame()
    })
  }
  
  /**
   * 鼠标进入容器时的处理函数
   * 设置标志位以暂停滚动
   */
  function onMouseEnter () {
    isMouseHover = true
  }
  
  /**
   * 鼠标离开容器时的处理函数
   * 恢复滚动状态
   */
  function onMouseLeaver () {
    isMouseHover = false
  }
  // 组件挂载后开始执行动画
  onMounted(doAnimationFrame)
  
  // 组件销毁前设置结束标志,停止动画
  onBeforeUnmount(() => {
    end = true
  })
  
  /**
   * 重置滚动位置到初始状态
   */
  function reset () {
    top = 0;
    refresh();
  }
  
  // 暴露reset方法供外部调用
  defineExpose({
    reset
  })
  
  </script>
  <template>
    <div
      ref="box"
      class="hb-admin-roll-list-com"
      @mouseenter="onMouseEnter"
      @mouseleave="onMouseLeaver"
    >
      <!-- 滚动内容容器1 -->
      <div
        ref="refRoll1"
        class="roll-item"
      >
        <div class="list-item">
          <slot />
        </div>
      </div>
      <!-- 滚动内容容器2(用于实现无缝滚动效果) -->
      <div
        ref="refRoll2"
        class="roll-item"
      />
    </div>
  </template>
  <style scoped>
  .hb-admin-roll-list-com{
    width: 100%;
    height: 100%;
    overflow: hidden;
    position: relative;
  }
  
  .hb-admin-roll-list-com::-webkit-scrollbar{
    display: none;
  }
  
  .roll-item{
    width: 100%;
    position: absolute;
  }
  
  .list-item{
  }
  </style>
        使用方法
基本用法
            
            
              vue
              
              
            
          
          <template>
  <SeamlessScroll :speed="800" direction="up">
    <div>滚动内容1</div>
    <div>滚动内容2</div>
    <div>滚动内容3</div>
  </SeamlessScroll>
</template>
<script setup>
import SeamlessScroll from './components/SeamlessScroll.vue'
</script>
        属性说明
| 属性名 | 类型 | 默认值 | 说明 | 
|---|---|---|---|
| speed | Number | 1000 | 滚动速度,数值越大滚动越慢 | 
| direction | String | 'up' | 滚动方向,可选 'up' 或 'down' | 
方法说明
| 方法名 | 说明 | 
|---|---|
| reset() | 重置滚动位置到初始状态 | 
调用方法示例
            
            
              vue
              
              
            
          
          <template>
  <SeamlessScroll ref="scrollRef" :speed="1200" direction="down">
    <div v-for="item in list" :key="item.id">
      {{ item.content }}
    </div>
  </SeamlessScroll>
  <button @click="resetScroll">重置滚动</button>
</template>
<script setup>
import { ref } from 'vue'
import SeamlessScroll from './components/SeamlessScroll.vue'
const scrollRef = ref(null)
const resetScroll = () => {
  scrollRef.value.reset()
}
</script>
        工作原理
该组件通过以下方式实现无缝滚动效果:
- 创建两个相同的滚动容器(refRoll1 和 refRoll2)
 - 使用 
requestAnimationFrame实现高性能动画 - 通过 CSS 
transform: translate3d()控制两个容器的位置 - 当一个容器完全移出视野时,将其移动到另一个容器的末尾
 - 通过不断更新 
top值实现滚动效果 - 利用 
clientHeight计算容器高度,确保内容无缝衔接 
注意事项
- 确保父容器有明确的高度设置
 - 滚动内容需要有明确的高度
 - 组件会自动隐藏滚动条
 - 鼠标悬停可临时暂停滚动效果