JS实现丝滑文字滚动
公告栏、弹幕、股票 ticker……垂直文字滚动是前端最常见的动效之一。本文用纯原生代码拆解一条「克隆 + 逐帧滚动」的实现思路,涵盖布局、滚动、边界衔接三大要点,开箱即用,零依赖零配置。
效果预览
一、布局:一行标题 + 一条列表
HTML 极简骨架:
<div class="container"><h1 class="title">最新公告</h1><ul class="list"><li>把大象装冰箱总共分几步?</li><li>1. 邓哥打开冰箱门</li><li>2. 邓哥把大象放进去</li><li>3. 邓哥关上冰箱门</li></ul>
</div>
CSS 只做两件事:
.container
负责背景色与水平排版.list
固定高度并隐藏溢出内容,为滚动做准备
二、核心算法:克隆 + 逐帧滚动
1.克隆首项 —— 无缝衔接的秘诀
当最后一项滚动到可视区后,必须立即回到第一项而不闪屏。最简单做法:把第一项克隆一份追加到列表末尾。这样「最后一项」和「第一项」之间永远有一条平滑过渡。
const list = document.querySelector('.list');
const firstItem = list.children[0].cloneNode(true);
list.appendChild(firstItem);
2.逐帧滚动 —— 手写 Easing
浏览器原生 scrollTop
没有动画,我们用 setInterval
在 300 ms 内完成一次 30 px 的位移动画:
let curIndex = 0;
const itemHeight = 30;
const duration = 300; // 动画耗时
const interval = 10; // 每帧间隔
const dis = itemHeight / (duration / interval);function moveNext() {let from = curIndex * itemHeight;let to = (curIndex + 1) * itemHeight;let timer = setInterval(() => {from += dis;if (from >= to) {clearInterval(timer);curIndex++;// 到达克隆项时瞬间归零,形成无缝循环if (curIndex === list.children.length - 1) {curIndex = 0;list.scrollTop = 0;}} else {list.scrollTop = from;}}, interval);
}
三、边界处理:回到起点不闪屏
当 curIndex
等于克隆项索引时,立即把 scrollTop
设为 0,人眼几乎察觉不到跳变,从而形成无限循环。
四、一行命令替换内容
只要保持每条文本高度一致,替换 <ul>
的 innerHTML
即可热插播新公告,无需重启动画逻辑。
总结
、一行命令替换内容
只要保持每条文本高度一致,替换 <ul>
的 innerHTML
即可热插播新公告,无需重启动画逻辑。
总结
「克隆第一项 + 逐帧滚动」是公告栏场景下最轻量的无限循环方案,可让文字像胶片一样永远滚动,不闪、不抖、不掉帧。