
本文深入探讨了在javascript动画中正确使用缓动函数(easing functions)的关键,特别强调了时间参数`t`的准确管理。通过解释缓动函数的`t, b, c, d`参数,并指出常见的时间计算误区,文章提供了一种通过记录动画开始时间来计算相对时间`animtime`的解决方案。结合`requestanimationframe`,本文通过实例代码展示了如何实现平滑、可控的动画效果,确保缓动函数在任何时刻都能按预期工作。
缓动函数(Easing Functions)是动画领域中用于控制动画速度变化的数学函数,它们能够使动画效果从简单的线性运动变得更加自然和富有表现力,例如加速、减速、回弹等。大多数缓动函数都遵循一个标准的参数签名:easingFunction(t, b, c, d)。
例如,一个简单的线性缓动函数可以表示为 c * t / d + b。当 t=0 时,函数返回 b;当 t=d 时,函数返回 c + b,即起始值加上总变化量,达到目标值。
在实际开发中,开发者常遇到的一个问题是 t 参数的计算方式。如果简单地将 performance.now()(一个表示页面加载以来毫秒数的绝对时间戳)直接作为 t 传入缓动函数,会导致动画行为异常。
问题分析:performance.now() 提供的是一个自页面加载或特定高精度时间源以来的时间戳。如果动画在代码执行的某个时刻(例如,5秒后)才启动,而 t 仍然从这个全局时间戳开始计算,那么缓动函数会认为动画已经运行了很长时间,导致动画不是从起始值 b 开始,而是从一个较大的中间值甚至超出最终值的状态“跳入”。这是因为缓动函数期望 t 是一个相对于动画开始时刻的增量时间,而非绝对时间。
立即学习“Java免费学习笔记(深入)”;
解决 t 参数误用的关键在于,为每个独立的动画实例维护一个明确的开始时间。当动画被触发时,记录下当前的 performance.now() 作为该动画的 startTime。在动画的每一帧中,将当前时间 performance.now() 减去 startTime,从而得到动画已经运行的相对时间,这个相对时间就是缓动函数所需的 t。
实现步骤:
以下示例展示了如何在Canvas上使用缓动函数驱动一个圆形的运动动画,并通过点击Canvas来启动/重启动画。
// 1. 缓动函数定义 (来自 https://spicyyoghurt.com/tools/easing-functions)
// easeLinear: 线性缓动
const easeLinear = (t, b, c, d) => c * t / d + b;
// easeInOutQuad: 二次方缓入缓出缓动
const easeInOutQuad = (t, b, c, d) => (t /= d * 0.5) < 1 ? c * 0.5 * t * t + b : -c * 0.5 * ((t - 1) * (t - 3) - 1) + b;
// 2. 动画状态变量
let animating = false;
let startTime;
const animDuration = 2000; // 动画总时长 2000 毫秒
// 获取 Canvas 元素及其上下文
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
// 3. 监听 Canvas 点击事件,触发动画
canvas.addEventListener("click", () => {
startTime = performance.now(); // 记录动画开始时间
// 如果当前没有动画在进行,则启动 requestAnimationFrame 循环
if (!animating) {
requestAnimationFrame(mainLoop);
animating = true; // 设置动画进行中标志
}
});
// 4. 动画主循环函数
function mainLoop(currentTime) {
ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除 Canvas 内容
if (startTime !== undefined) { // 确保 startTime 已经被设置
// 计算动画已进行的相对时间
const animTime = currentTime - startTime;
// 计算圆形在X轴上的位置,使用线性缓动
// b = -20 (起始X), c = canvas.width + 40 (总变化量), d = animDuration
// 目标X = b + c = -20 + (canvas.width + 40) = canvas.width + 20
const x = easeLinear(animTime, -20, canvas.width + 40, animDuration);
// 计算圆形在Y轴上的位置,使用缓入缓出缓动
// b = 20 (起始Y), c = canvas.height - 40 (总变化量), d = animDuration
// 目标Y = b + c = 20 + (canvas.height - 40) = canvas.height - 20
const y = easeInOutQuad(animTime, 20, canvas.height - 40, animDuration);
// 绘制圆形
ctx.beginPath();
ctx.arc(x, y, 20, 0, Math.PI * 2);
ctx.fill();
// 检查动画是否完成
if (animTime < animDuration) {
// 如果动画未完成,继续下一帧
requestAnimationFrame(mainLoop);
} else {
// 动画完成,重置 animating 标志
animating = false;
// 可选:将动画元素设置为最终状态,避免因浮点误差导致位置不精确
// ctx.clearRect(0, 0, canvas.width, canvas.height);
// ctx.beginPath();
// ctx.arc(easeLinear(animDuration, -20, canvas.width + 40, animDuration),
// easeInOutQuad(animDuration, 20, canvas.height - 40, animDuration),
// 20, 0, Math.PI * 2);
// ctx.fill();
}
}
}<!-- HTML 结构 -->
<style>
canvas { border: 1px solid black; }
</style>
<div>点击 Canvas 区域来开始 / 重启动画。</div>
<canvas id="canvas" width="500" height="200"></canvas>正确使用缓动函数的关键在于精确管理时间参数 t。通过记录动画的 startTime 并计算相对时间 animTime = currentTime - startTime,我们可以确保缓动函数始终以预期的方式工作,无论动画何时被触发。结合 requestAnimationFrame,这种方法能够创建流畅、高效且易于控制的JavaScript动画,极大地提升用户体验。掌握这一核心概念,将使你在Web动画开发中更加游刃有余。
以上就是JavaScript 动画缓动函数:精确控制时间与动画流程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号