
本教程详细介绍了如何将一个基于鼠标移动事件触发的视差文本动画转换为自动播放效果。通过利用javascript的requestanimationframe api,我们实现了在指定时间(例如10秒)内,文本元素自动进行水平滚动和视差位移,从而摆脱了对用户交互的依赖,创建出流畅且无需干预的动态视觉体验。
原始动画机制解析
在深入实现自动播放之前,我们首先理解原始的鼠标事件驱动视差动画是如何工作的。该动画通过JavaScript监听mousemove事件,动态更新一个CSS自定义属性--x,进而影响文本元素的text-shadow和transform属性,从而创建出视差效果。
HTML 结构:
HTML结构包含一个section作为容器,内部的div.text包含多个h2元素。每个h2元素通过内联样式定义了一个CSS自定义属性--i,这个变量在后续的CSS计算中用于控制视差效果的强度。
CSS 样式:
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@900&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "poppins";
font-weight: 900;
}
section {
position: relative;
width: 100vw;
height: 100vh;
overflow: hidden;
background: #111;
}
.text {
position: relative;
transform: skewY(350deg) translateY(-200px);
animation: animatecolor 5s linear infinite; /* 背景色调动画 */
}
@keyframes animatecolor {
0% { filter: hue-rotate(0deg); }
100% { filter: hue-rotate(360deg); }
}
.text h2 {
position: relative;
width: 100%;
font-size: 8em;
color: #fff;
pointer-events: none;
line-height: 1em;
white-space: nowrap;
/* 关键:使用 --x 和 --i 控制文本阴影和位移 */
text-shadow: calc(var(--x)) 100px 0 rgba(255, 255, 255, 0.1);
transform: translateX(calc(0% - var(--x) * var(--i)));
}
.text h2 span {
color: #0f0;
margin: 0 10px;
}
.text h2 span:nth-child(even) {
color: transparent;
-webkit-text-stroke: 2px #fff;
}CSS代码中,.text h2元素的text-shadow和transform: translateX属性是实现视差效果的关键。它们都依赖于--x变量,并通过calc()函数结合--i变量计算出不同的位移量,从而使不同行文本产生不同的滚动速度,形成视差感。
原始 JavaScript 逻辑:
const position = document.documentElement;
position.addEventListener("mousemove", (e) => {
position.style.setProperty("--x", e.clientX + "px");
});这段JavaScript代码监听了整个文档的mousemove事件。每当鼠标移动时,它会获取鼠标的X坐标(e.clientX),并将其值设置为根元素(document.documentElement)上的CSS自定义属性--x。这样,--x的值会实时跟随鼠标的水平移动而变化,驱动CSS动画。
转换为自动播放动画
要将这种鼠标事件驱动的动画转换为自动播放,我们需要用一个程序化的方式来模拟--x变量的连续变化,而不是依赖鼠标输入。requestAnimationFrame API是实现平滑、高效动画的最佳选择。
requestAnimationFrame 简介
requestAnimationFrame是浏览器提供的一个API,它会告诉浏览器你希望执行一个动画,并请求浏览器在下一次重绘之前调用指定的更新函数。相比于setTimeout或setInterval,它的优势在于:
- 性能优化: 浏览器会在最佳时机(通常是显示器刷新率)调用回调函数,确保动画流畅且不会过度消耗CPU。
- 节能: 当页面不在活动标签页时,动画会自动暂停,节省电量。
- 同步: 确保动画与其他浏览器渲染操作同步,避免画面撕裂。
重构 JavaScript 代码
我们将修改JavaScript部分,使用requestAnimationFrame来自动更新--x变量,并设置一个动画持续时间。
const position = document.documentElement; // 获取根元素,用于设置CSS变量
let startTime = Date.now(); // 记录动画开始时间
let xValue = 0; // 用于累加的 x 坐标值
const animateScroll = () => {
// 检查动画是否已持续 10 秒(10000 毫秒)
if (Date.now() - startTime > 10000) {
return; // 动画结束,停止递归调用
}
// 更新 --x CSS变量,每次增加 1px
// xValue++ 会使文本向右滚动,如果需要向左滚动,可以使用 xValue--
position.style.setProperty("--x", (xValue++) + "px");
// 请求浏览器在下一次重绘前再次调用 animateScroll 函数
requestAnimationFrame(animateScroll);
};
// 启动动画
animateScroll();代码解释:
- startTime = Date.now();: 记录动画开始的精确时间戳。
- xValue = 0;: 初始化一个变量xValue,它将作为自动滚动的X坐标值。
-
animateScroll() 函数:
- if (Date.now() - startTime > 10000): 这是动画持续时间的控制逻辑。当当前时间与startTime之差超过10000毫秒(即10秒)时,函数返回,停止requestAnimationFrame的递归调用,动画自然结束。
- position.style.setProperty("--x", (xValue++) + "px");: 这是核心动画逻辑。每次animateScroll被调用时,xValue会递增,并将当前值设置为CSS变量--x。xValue++实现的是向右滚动的效果;如果需要向左滚动,可以改为xValue--。
- requestAnimationFrame(animateScroll);: 关键步骤。它告诉浏览器在下一次屏幕刷新时再次调用animateScroll函数,从而形成一个连续的动画循环。
- animateScroll();: 在脚本加载后立即调用一次animateScroll,启动整个动画过程。
完整的代码示例
为了方便测试和理解,以下是完整的HTML、CSS和修改后的JavaScript代码:
HTML (不变)
CSS (不变)
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@900&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "poppins";
font-weight: 900;
}
a {
text-decoration: none;
}
section {
position: relative;
width: 100vw;
height: 100vh;
overflow: hidden;
background: #111;
}
.text {
position: relative;
transform: skewY(350deg) translateY(-200px);
animation: animatecolor 5s linear infinite;
}
@keyframes animatecolor {
0% {
filter: hue-rotate(0deg);
}
100% {
filter: hue-rotate(360deg);
}
}
.text h2 {
position: relative;
width: 100%;
font-size: 8em;
color: #fff;
pointer-events: none;
line-height: 1em;
white-space: nowrap;
text-shadow: calc(var(--x)) 100px 0 rgba(255, 255, 255, 0.1);
transform: translateX(calc(0% - var(--x) * var(--i)));
}
.text h2 span {
color: #0f0;
margin: 0 10px;
}
.text h2 span:nth-child(even) {
color: transparent;
-webkit-text-stroke: 2px #fff;
}JavaScript (修改后)
const position = document.documentElement;
let startTime = Date.now(); // 记录动画开始时间
let xValue = 0; // 用于累加的 x 坐标值
const animateScroll = () => {
// 检查动画是否已持续 10 秒(10000 毫秒)
if (Date.now() - startTime > 10000) {
return; // 动画结束,停止递归调用
}
// 更新 --x CSS变量,每次增加 1px
position.style.setProperty("--x", (xValue++) + "px");
// 请求浏览器在下一次重绘前再次调用 animateScroll 函数
requestAnimationFrame(animateScroll);
};
// 启动动画
animateScroll();注意事项与优化
- 动画持续时间: 要修改动画的持续时间,只需调整if (Date.now() - startTime > 10000)中的数字。例如,改为20000即为20秒。
-
动画速度与方向:
- 速度: 调整xValue++的增量可以改变滚动速度。例如,xValue += 2会使滚动速度加倍。
- 方向: 将xValue++改为xValue--可以使文本向左滚动。
-
无限循环动画: 如果希望动画无限循环,只需移除时间限制的if语句即可:
const animateScroll = () => { position.style.setProperty("--x", (xValue++) + "px"); requestAnimationFrame(animateScroll); }; animateScroll(); - 性能考量: requestAnimationFrame本身就是为高性能动画设计的。对于更复杂的动画,应避免在回调函数中执行耗时的DOM操作或复杂计算。
- 兼容性: requestAnimationFrame在现代浏览器中广泛支持。对于老旧浏览器,可能需要添加polyfill,但这在当前前端开发中已不常见。
- CSS变量的灵活性: 本案例充分展示了CSS自定义属性(CSS变量)与JavaScript结合的强大之处。通过JavaScript动态更新CSS变量,可以实现高度灵活且性能优异的动态样式效果。
总结
通过本教程,我们成功地将一个依赖用户鼠标事件的视差文本动画,改造为一个完全自动播放的动画效果。核心在于利用requestAnimationFrame API来平滑、高效地更新CSS自定义属性--x,从而驱动CSS中的text-shadow和transform属性变化。这种方法不仅实现了动画的自动化,还保证了动画的流畅性和性能,为创建无需用户干预的动态网页元素提供了有效的解决方案。











