动画效果
在工业监控系统、生产看板等场景中,经常需要模拟生产线的动态运行效果。本文将基于 Vue3 和 requestAnimationFrame 实现一个高性能的横向循环滚动效果,完美模拟生产线传输带的视觉体验。我们将从代码实现到原理分析,全面讲解如何打造流畅、高效的滚动动画。
一、效果展示与应用场景
先来看下最终实现的效果:一系列生产物料图标将沿着横向轨道从左向右连续滚动,到达终点后自动循环,形成无限滚动的生产线效果。这种效果非常适合:
- 工业监控大屏中的生产线模拟
- 生产进度可视化展示
- 物流传输过程动态演示
- 数据看板中的动态元素展示
相比传统的轮播组件,这种实现方式具有更高的性能和更自然的动画效果,尤其适合长时间运行的监控场景。
二、核心实现方案
我们将使用以下技术栈和方案:
- Vue3 + TypeScript:提供组件化开发和类型安全
- requestAnimationFrame:实现高性能动画,替代传统的 setInterval
- CSS 滚动优化:隐藏滚动条并优化滚动容器样式
- 循环逻辑设计:通过重置 scrollLeft 实现无缝循环
下面是完整的实现代码:
1. 模板结构(Template)
<template><!-- 生产线滚动容器 --><div class="ktscx-box" ref="scrollDom"><div class="ktscx"><!-- 生产线上的物品,这里循环生成40个 --><divclass="ktscx-item"v-for="(item, index) in 40":key="index"></div></div></div>
</template>
模板结构非常简洁,主要包含两个层级:
- 外层
ktscx-box
:作为滚动容器,通过 ref 绑定到组件实例 - 内层
ktscx
:包含所有滚动项的容器,设置为 200% 宽度确保能产生滚动效果 - 循环生成的
ktscx-item
:生产线中的物品元素,共 40 个
2. 脚本逻辑(Script)
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';// 定义滚动容器的ref,指向DOM元素
const scrollDom = ref<HTMLDivElement | null>(null);
let timer: number | null = null; // 动画帧ID,用于控制动画// 开始横向滚动(从左向右视觉效果)
const startScroll = () => {if (!scrollDom.value) return;// 启动动画帧,开始滚动timer = requestAnimationFrame(scrollStep);
};// 停止滚动
const stopScroll = () => {if (timer) {cancelAnimationFrame(timer);timer = null;}
};// 动画帧执行的滚动逻辑
const scrollStep = () => {const moveDom = scrollDom.value;if (!moveDom) {stopScroll();return;}// 每次滚动的步长(负值表示向右滚动)const step = -1; moveDom.scrollLeft += step;// 计算最大可滚动距离 = 内容总宽度 - 容器可视宽度const maxScrollLeft = moveDom.scrollWidth - moveDom.clientWidth;// 当滚动到最左侧时,重置到最右侧(形成循环)if (moveDom.scrollLeft <= 0) {moveDom.scrollLeft = maxScrollLeft; }// 继续请求下一帧动画,形成连续滚动timer = requestAnimationFrame(scrollStep);
};// 组件挂载时启动滚动
onMounted(() => {startScroll();
});// 组件卸载时停止滚动,防止内存泄漏
onUnmounted(() => {stopScroll();
});
</script>
脚本逻辑解析:
核心变量:
scrollDom
:通过 ref 绑定到滚动容器 DOM 元素timer
:存储动画帧 ID,用于控制动画的启动和停止
动画控制函数:
startScroll()
:启动滚动动画,通过 requestAnimationFrame 触发第一帧stopScroll()
:停止滚动动画,通过 cancelAnimationFrame 取消动画帧scrollStep()
:每帧执行的滚动逻辑,是实现动画的核心
滚动原理:
- 通过修改容器的
scrollLeft
属性实现滚动 - 负的步长值(
step = -1
)使内容从左向右滚动 - 当滚动到最左侧(
scrollLeft <= 0
)时,重置到最大滚动位置,实现循环
- 通过修改容器的
3. 样式设计(Style)
<style scoped lang="scss">
.ktscx-box {width: 83%;height: 20px;overflow-x: auto; // 允许横向滚动position: absolute;top: 256px;margin-left: 3%;// 隐藏滚动条,提升视觉体验&::-webkit-scrollbar {display: none;}.ktscx {width: 200%; // 宽度设为200%,确保内容超出容器宽度产生滚动height: 20px;display: flex;justify-content: space-around; // 物品均匀分布align-items: center;.ktscx-item {width: 20px;height: 10px;// 使用背景图作为生产线物品background-image: url('@/assets/images/yundong4.png');background-size: 100% 100%;background-repeat: no-repeat;flex-shrink: 0; // 防止物品被压缩变形}}
}
</style>
样式设计要点:
滚动容器样式:
- 设置
overflow-x: auto
允许横向滚动 - 使用
::-webkit-scrollbar { display: none }
隐藏滚动条 - 固定高度和宽度,确保滚动区域可控
- 设置
内容容器样式:
- 宽度设为 200%,确保内容宽度超过容器宽度,产生滚动空间
- 使用 flex 布局使物品均匀分布
滚动项样式:
- 固定宽高,使用背景图展示物品
flex-shrink: 0
确保物品不会被压缩变形
三、核心技术点解析
1. requestAnimationFrame 为什么比 setInterval 更好?
本实现使用 requestAnimationFrame 而非传统的 setInterval 来驱动动画,原因如下:
- 与浏览器刷新同步:requestAnimationFrame 会在浏览器每次重绘前执行,与显示器刷新率(通常 60Hz)保持同步,避免动画卡顿
- 自动性能调整:在性能较低的设备上,浏览器会自动降低执行频率,保证动画的流畅度
- 后台暂停:当页面处于后台或隐藏标签页时,动画会自动暂停,减少不必要的性能消耗
- 精确计时:基于系统时间计算帧间隔,避免 setInterval 可能产生的累积误差
对于生产线这种需要长时间运行的动画,这些优势尤为重要。
2. 循环滚动的实现原理
循环滚动的核心在于巧妙利用 scrollLeft
属性和内容宽度:
scrollLeft
属性表示元素内容向左滚动的像素数:- 增大
scrollLeft
→ 内容向左移动 - 减小
scrollLeft
→ 内容向右移动
- 增大
循环逻辑:
- 当内容滚动到最左侧(
scrollLeft <= 0
)时 - 立即将
scrollLeft
重置为最大可滚动距离(maxScrollLeft
) - 由于内容容器宽度是 200%,重置后视觉上看不出跳跃,形成无缝循环
- 当内容滚动到最左侧(
最大可滚动距离计算:
const maxScrollLeft = moveDom.scrollWidth - moveDom.clientWidth;
其中
scrollWidth
是内容总宽度,clientWidth
是容器可视宽度。
四、功能扩展与优化
基于以上实现,我们可以进行一些实用的扩展:
1. 添加入交互控制
<!-- 在模板中添加控制按钮 -->
<div class="controls"><button @click="startScroll">启动</button><button @click="stopScroll">停止</button>
</div>
2. 滚动速度调节
// 添加速度控制变量
const speed = ref(1);// 在scrollStep中使用speed
const step = -speed.value;
3. 鼠标悬停暂停
<!-- 修改滚动容器 -->
<div class="ktscx-box" ref="scrollDom" @mouseenter="stopScroll" @mouseleave="startScroll">
4. 性能优化建议
- 对于大量滚动项(超过 100 个),考虑使用虚拟列表技术
- 添加
will-change: scroll-position
提示浏览器优化滚动性能 - 避免在
scrollStep
中执行复杂计算或 DOM 操作 - 滚动项使用相同尺寸,减少布局重排
五、总结
本文基于 Vue3 实现了一个高性能的横向循环滚动效果,完美模拟生产线传输带。核心要点包括:
使用 requestAnimationFrame 实现流畅动画,替代传统的 setInterval 通过控制 scrollLeft 属性值实现滚动效果,负步长产生从左到右的视觉体验 利用内容宽度和容器宽度的关系,实现无缝循环滚动 隐藏滚动条并优化样式,提升视觉体验
这种实现方式性能优异、代码简洁,非常适合工业监控、生产看板等场景。根据实际需求,你可以进一步扩展功能,如添加速度控制、方向切换、交互暂停等特性。
宝子们加加关注,会持续更新前端学习内容。