js缓动动画 js逐帧动画

本文深入探讨了正确使用 JavaScript 动画缓动函数的关键,尤其强调了时间参数 `t` 的精确管理。通过解释 `t`、`b`、`c`、`d`` 参数的缓动功能,并指出了常见的时间计算错误,本文提供了一种通过记录动画开始时间来计算相对时间 `animtime` 的解决方案。结合 `requestanimationframe`,本文通过代码示例展示了如何实现平滑可控的动画效果,确保缓动函数在任何时候都能按预期工作。理解缓动函数及其核心参数
缓动函数(easingFunction)是用于控制动画速度的数学函数,它可以使动画效果从简单的线性运动变得更加自然和富有表现力,例如加速、减速、回弹等。大多数缓动函数遵循标准的参数签名:easingFunction(t, b, c, d)。其中,t(时间):当前时间。这是动画从开始帧到当前帧的相对时间。(begin):动画属性的起始值。c (change):动画属性的总变化量(即目标值减去目标值)。d (duration):动画的总时长。
例如,一个简单的线性慢动作函数可以表示为 c * t / d b。当 t=0 时,函数返回 b;当 t=d 时,函数返回 c b,即初始值加上总变化量,达到目标值。常见问题:时间参数 t 的团用
在实际开发中,开发者经常遇到的问题之一是 t 参数的计算方法。如果直接将 performance.now()(页面加载后以毫秒为单位的绝对时间戳)作为 t 传递给慢动作函数,会导致动画行为异常。它仍然基于这个全局时间戳进行计算,因此慢动作函数会认为动画已经运行了很长时间,导致动画无法从初始值 b 开始播放。这是因为慢动作函数期望 t 是相对于动画开始时间的增量时间,而不是绝对时间 startTime。在动画的每一帧中,用 performance.now() 减去 startTime,得到动画已经运行的相对时间,这个相对时间就是慢动作函数所需的 t 值。
123 查看详情
实现步骤:定义动画函数:使用标准的 t、b、c、d 签名参数。初始化动画状态:animating:指示动画是否正在进行的标志。startTime:记录动画开始的时间 performance.now() 值。requestAnimationFrame 创建一个循环,确保动画在浏览器下一帧之前执行。在每一帧中,计算 animTime = currentTime - startTime。AnimTime 作为 t 传递,并计算当前动画属性的值。判断 animTime 是否小于 animDuration。false。示例代码:使用新动函数实现 Canvas 动画
以下示例展示了如何使用 Canvas 上的新动函数驱动圆形运动动画,并通过点击 Canvas 来启动/重新开始动画。
// 1.缓动函数定义(摘自https://spicyyoghurt.com/tools/easing-functions)// escapeLinear: 线性 easeInOutQuad = (t, b, c, d) =gt; c * t / d b;// escapeInOutQuad: 发发方扐入扐出const easeInOutQuad = (t, b, c, d) =gt; (t /= d * 0.5) lt; 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";,() =gt; { startTime = performance.now(); // 记录动画开始时间 // 如果当前没有动画正在进行,则启动 requestAnimationFrame 循环 if (!animating) { requestAnimationFrame(mainLoop); animating = true; // 设置动画正在进行标志 }});// 4. 函数mainLoop(currentTime) { ctx.clearRect(0,0,canvas.width,canvas.height); // 清除画布内容 if (startTime !== undefined) { // 确保 startTime 已设置 // 计算动画之间的相对时间 const animTime = currentTime - startTime; // 计算圆在 X 轴上的位置,使用线性运动 // b = -20 (起始 X),c = canvas.width 40 (总长度),d = animDuration // targetX = 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 // targetY = b c = 20(可以)
vas.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 lt; animDuration) { // 如果动画未完成,则继续下一帧 requestAnimationFrame(mainLoop); } else { // 动画完成,重置动画标志 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(); } }} 电影后名生lt;!-- HTML 结构 --gt;lt;stylegt; canvas { border: 1px solid black; }lt;/stylegt;lt;divgt;点击 Canvas 区域启动/重启动画。lt;/divgt;lt;canvas id=quot;canvasquot; width=quot;500quot; height=quot;200quot;gt;lt;/canvasgt; 登录后复制的重要性和最佳实践 requestAnimationFrame:始终使用 requestAnimationFrame 来驱动动画,而不是 setTimeout 或 setInterval。 requestAnimationFrame 会在浏览器准备好渲染下一帧时调用回调函数,这样可以确保动画与浏览器同步绘制,减少丢帧,提高流畅度,节省电量。动画状态管理:使用 animating 这样的标志来管理动画的状态非常重要,它可以防止同一个动画重复启动,或者在动画进行过程中尝试启动另一个动画,从而造成冲突。准确的 b 和 c 参数:确保慢动作函数中的 b(起始值) 和 c(总性性值) 参数与你想要的动画属性的实际起始值和目标值相匹配。c 应该始终是目标值 - 起始值。
动画结束处理:当 animTime gt;= animDuration 时,动画应该停止。此时,可以考虑将动画属性设置为最终目标值,以避免浮点数计算误差导致动画元素停留在略微不准确的位置。总结
正确使用动画函数的关键在于准确管理时间参数 t。通过记录动画的开始时间并计算相对时间 animTime = currentTime - startTime,我们可以确保动画函数始终按预期工作,无论动画何时触发。使用 requestAnimationFrame 方法可以创建流畅、高效且易于控制的 JavaScript 动画,极大地提升用户体验。掌握这一核心概念将使您在 Web 动画开发中更加流畅。
以上是 JavaScript 动画函数:精确控制时间和动画流程。
详细内容,更多请关注乐哥常识网其他相关文章!这是在看: JavaScript 中将日期时间国际时间(英国时间) JavaScript 设计模式在音乐流媒体服务中的应用与优化 JavaScript 将日期转换为英国时间(英国时间) JavaScript DOM 操作:动态更新列表,避免重复渲染 JavaScript 设计模式实践:构建模块化音乐流媒体服务