无缝滚动是一种常见的网页效果,它可以使内容在页面上连续滚动,而不会出现明显的断裂,且鼠标移入滚动区域会暂停滚动。这种效果在新闻滚动、广告展示、大屏呈现等场景中非常常见。下面我们将介绍如何使用JavaScript和CSS来实现无缝滚动组件,本文实现的组件使用非常简单,只要在html中引入css和js,在需要实现无缝滚动的元素上添加约定的类(cl-seamless-container、cl-seamless-list)就可以自动实现无缝滚动。
HTML结构
首先,我们需要创建一个包含滚动内容的HTML结构,这里我们创建两个滚动示例,每个滚动项的列表数目不同,其中cl-seamless-container类的元素表示滚动组件的容器,cl-seamless-list类包含的是要滚动显示的列表项。接下来将介绍如何仅通过添加这两个类就能实现一个无缝滚动的效果且能够自适应列表项高度。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./animation.css">
<title>动画组件</title>
</head>
<body>
<h3>无缝滚动组件示例一</h3>
<div class="cl-seamless-container">
<ul class="cl-seamless-list">
<li>滚动项1</li>
<li>滚动项2</li>
<li>滚动项3</li>
</ul>
</div>
<h3>无缝滚动组件示例二</h3>
<div class="cl-seamless-container">
<ul class="cl-seamless-list">
<li>滚动项1</li>
<li>滚动项2</li>
<li>滚动项3</li>
<li>滚动项4</li>
<li>滚动项5</li>
<li>滚动项6</li>
<li>滚动项7</li>
<li>滚动项8</li>
<li>滚动项9</li>
<li>滚动项10</li>
</ul>
</div>
<script type="module" src="./animation.js"></script>
</body>
</html>
CSS样式
在进行具体的样式设置之前,先来分析一下怎么做到无缝滚动,下图中蓝色容器的内容才是可见的,想象两个完全相同的列表项向上滑动,从最初的0%的位置滑动到100%的位置后,再次恢复到最初0%的位置,我们发现0%和100%的位置容器内呈现的内容是一样的,也就是说用户感知不到100%到0%的这个切换的抖动,如此循环下去就实现了无缝滚动的效果。因此实现无缝滚动效果需要注意两个关键的点:
- 容器的高度不能超过滚动列表的高度,否则就会出现抖动;
- 需要复制一份完全相同的滚动列表填补滚动过程的空隙;
说明:通过类似的思路也可以实现横向无缝滚动,推荐读者动手去试试
接下来,我们就为滚动容器和滚动列表设置一些基本的CSS样式,主要使用css的transform中的translate平移来实现列表向上滚动的动画,@keyframes cl-scrolling定义了关键帧,translate(0px, 0%)表示列表最初的位置,translate(0px, -100%)表示y轴向上平移100%的位置,animation: cl-scrolling 6s infinite linear;表示在6s内完成0%到100%的一次动画并一直循环下去。显然,滚动列表的高度不断增加也会导致滚动的速度变快,因为6s内要完成一次完整滑动,可能会导致滚动太快而导致感知不适。因此,这里并没有在css中设置动画,而是借助js调节合适的速率后再进行设置动画。
.cl-seamless-container {
overflow: hidden;
}
.cl-seamless-list {
margin: auto 0;
padding: auto 0;
/* 滚动快慢会受滚动列表项的高度影响,在js中调节速率进行控制 */
/* animation: cl-scrolling 6s infinite linear; */
}
/* 鼠标移入滚动区域变成手型 */
.cl-seamless-container:hover .cl-seamless-list {
cursor: pointer;
}
/* 鼠标移入滚动区域暂停动画 */
.cl-seamless-container.pause .cl-seamless-list {
animation-play-state: paused !important;
}
/* 动画关键帧 */
@keyframes cl-scrolling {
from {
transform: translate(0px, 0%);
}
to {
transform: translate(0px, -100%);
}
}
JavaScript逻辑
最后,我们需要编写JavaScript代码来控制滚动效果,JS代码主要实现如下功能:
- 设置容器的最大高度不能超过单个滚动列表的高度;
- 根据滚动列表项的高度调节动画播放速度;
- 复制滚动项列表并插入容器中;
- 监听鼠标移入和移出事件,向容器添加或移除pause类,实现暂停和恢复滚动效果;
function animation () {
var seamless_container = document.getElementsByClassName("cl-seamless-container");
for (let i = 0; i < seamless_container.length; i++) {
if (seamless_container[i].children.length > 0) {
// 限制每个容器的高度
let seamless_sub = seamless_container[i].children[0];
seamless_container[i].style="max-height: " + seamless_sub.clientHeight + "px";
// 调节滚动速率,使滚动速率不至于过快或过慢
let scroll_speed = Math.max(4, Math.ceil(seamless_sub.clientHeight / 35));
seamless_sub.style = "animation: cl-scrolling " + scroll_speed + "s infinite linear";
// 复制一份完全相同的列表,实现无缝滚动
seamless_container[i].innerHTML += seamless_container[i].innerHTML;
}
// 监听鼠标移入事件,暂停动画; 同时鼠标移出,继续动画
seamless_container[i].addEventListener("mouseenter", function(event) {
event.target.classList.add("pause");
});
seamless_container[i].addEventListener("mouseleave", function(event) {
event.target.classList.remove("pause");
})
}
}
animation();
以上就是实现Web无缝滚动的基本方法,最终效果见开篇的gif动画。