增强您的 Web 动画:像专业人士一样优化 requestAnimationFrame

增强您的 web 动画:像专业人士一样优化 requestanimationframe

流畅且高性能的动画在现代 web 应用程序中至关重要。然而,管理不当可能会使浏览器的主线程过载,导致性能不佳和动画卡顿。 requestanimationframe (raf) 是一种浏览器 api,旨在将动画与显示器的刷新率同步,确保与 settimeout 等替代方案相比更流畅的运动。但高效使用 raf 需要仔细规划,尤其是在处理多个动画时。

在本文中,我们将探讨如何通过集中动画管理、引入 fps 控制以及保持浏览器主线程响应来优化 requestanimationframe。

了解 fps 及其重要性

在讨论动画性能时,每秒帧数 (fps) 至关重要。大多数屏幕以 60 fps 刷新,这意味着 requestanimationframe 每秒被调用 60 次。为了保持流畅的动画,浏览器必须在每帧约 16.67 毫秒内完成其工作。

如果在单个帧中运行太多任务,浏览器可能会错过其目标帧时间,从而导致卡顿或丢帧。降低某些动画的 fps 有助于减少主线程的负载,从而在性能和流畅度之间取得平衡。

具有 fps 控制功能的集中式动画管理器可实现更好的性能

为了更有效地管理动画,我们可以通过共享循环集中处理动画,而不是在代码中分散多个 requestanimationframe 调用。集中式方法可最大程度地减少冗余调用,并更轻松地添加 fps 控制。

下面的animationmanager类允许我们在控制目标fps的同时注册和取消注册动画任务。默认情况下,我们的目标是 60 fps,但这可以根据性能需求进行调整。

class animationmanager {  private tasks: set = new set();  private fps: number = 60; // target fps  private lastframetime: number = performance.now();  private animationid: number | null = null; // store the animation frame id  private run = (currenttime: number) => {    const deltatime = currenttime - this.lastframetime;    // ensure the tasks only run if enough time has passed to meet the target fps    if (deltatime > 1000 / this.fps) {      this.tasks.foreach((task) => task(currenttime));      this.lastframetime = currenttime;    }    this.animationid = requestanimationframe(this.run);  };  public registertask(task: framerequestcallback) {    this.tasks.add(task);    if (this.tasks.size === 1) {      this.animationid = requestanimationframe(this.run); // start the loop if this is the first task    }  }  public unregistertask(task: framerequestcallback) {    this.tasks.delete(task);    if (this.tasks.size === 0 && this.animationid !== null) {      cancelanimationframe(this.animationid); // stop the loop if no tasks remain      this.animationid = null; // reset the id    }  }}export const animationmanager = new animationmanager();

在此设置中,我们计算帧之间的 deltatime,以确定基于目标 fps 是否已经过去了足够的时间进行下一次更新。这使我们能够限制更新频率,以确保浏览器的主线程不会过载。

实际示例:为具有不同属性的多个元素设置动画

让我们创建一个示例,为三个盒子设置动画,每个盒子都有不同的动画:一个缩放,另一个改变颜色,第三个旋转。

这是 html:

这是 css

.animated-box {  width: 100px;  height: 100px;  background-color: #3498db;  transition: transform 0.1s ease;}

现在,我们将添加 javascript 来为每个具有不同属性的框设置动画。一个会缩放,另一个会改变颜色,第三个会旋转。

第 1 步:添加线性插值 (lerp)

线性插值 (lerp) 是动画中常用的技术,用于在两个值之间平滑过渡。它有助于创建渐进且平滑的进程,使其成为随时间推移缩放、移动或更改属性的理想选择。该函数采用三个参数:起始值、结束值和标准化时间 (t),该时间确定过渡的距离。

来画数字人直播 来画数字人直播

来画数字人自动化直播,无需请真人主播,即可实现24小时直播,无缝衔接各大直播平台。

来画数字人直播 0 查看详情 来画数字人直播

function lerp(start: number, end: number, t: number): number {  return start + (end - start) * t;}

第 2 步:缩放动画

我们首先创建一个函数来为第一个框的缩放设置动画:

function animatescale(  scalebox: htmldivelement,  startscale: number,  endscale: number,  speed: number) {  let scalet = 0;  function scale() {    scalet += speed;    if (scalet > 1) scalet = 1;    const currentscale = lerp(startscale, endscale, scalet);    scalebox.style.transform = `scale(${currentscale})`;    if (scalet === 1) {      animationmanager.unregistertask(scale);    }  }  animationmanager.registertask(scale);}

第 3 步:彩色动画

接下来,我们为第二个框的颜色变化设置动画:

function animatecolor(  colorbox: htmldivelement,  startcolor: number,  endcolor: number,  speed: number) {  let colort = 0;  function color() {    colort += speed;    if (colort > 1) colort = 1;    const currentcolor = math.floor(lerp(startcolor, endcolor, colort));    colorbox.style.backgroundcolor = `rgb(${currentcolor}, 100, 100)`;    if (colort === 1) {      animationmanager.unregistertask(color);    }  }  animationmanager.registertask(color);}

第 4 步:旋转动画

最后,我们创建旋转第三个框的函数:

function animaterotation(  rotatebox: htmldivelement,  startrotation: number,  endrotation: number,  speed: number) {  let rotationt = 0;  function rotate() {    rotationt += speed; // increment progress    if (rotationt > 1) rotationt = 1;    const currentrotation = lerp(startrotation, endrotation, rotationt);    rotatebox.style.transform = `rotate(${currentrotation}deg)`;    // unregister task once the animation completes    if (rotationt === 1) {      animationmanager.unregistertask(rotate);    }  }  animationmanager.registertask(rotate);}

第 5 步:开始动画

最后,我们可以启动所有三个盒子的动画:

// Selecting the elementsconst scaleBox = document.querySelector("#animate-box-1") as HTMLDivElement;const colorBox = document.querySelector("#animate-box-2") as HTMLDivElement;const rotateBox = document.querySelector("#animate-box-3") as HTMLDivElement;// Starting the animationsanimateScale(scaleBox, 1, 1.5, 0.02); // Scaling animationanimateColor(colorBox, 0, 255, 0.01); // Color change animationanimateRotation(rotateBox, 360, 1, 0.005); // Rotation animation

主线程注意事项

使用 requestanimationframe 时,必须记住动画在浏览器的主线程上运行。主线程超载过多的任务可能会导致浏览器错过动画帧,从而导致卡顿。这就是为什么使用集中式动画管理器和 fps 控制等工具优化动画可以帮助保持流畅度,即使有多个动画也是如此。

结论

在 javascript 中有效管理动画需要的不仅仅是使用 requestanimationframe。通过集中动画并控制 fps,您可以确保动画更流畅、性能更高,同时保持主线程响应能力。在此示例中,我们展示了如何使用单个 animationmanager 处理多个动画,演示如何优化性能和可用性。虽然为了简单起见,我们专注于保持一致的 fps,但这种方法可以扩展到处理各种动画的不同 fps 值,尽管这超出了本文的范围。

github 存储库: https://github.com/jbassx/raf-optimization
stackblitz: https://stackblitz.com/~/github.com/jbassx/raf-optimization

领英: https://www.linkedin.com/in/josephciullo/

以上就是增强您的 Web 动画:像专业人士一样优化 requestAnimationFrame的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/450516.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月7日 22:53:09
下一篇 2025年11月7日 22:54:06

相关推荐

  • 使用 C++ 框架的最佳实践有哪些?

    c++++ 框架最佳实践可提升代码质量和性能:使用依赖注入,解耦对象和依赖项创建,提高可测试性和可维护性。遵循 solid 原则,提高代码可读性、可维护性和灵活性。利用智能指针管理资源,防止内存泄漏。进行单元测试,验证代码正确性和健壮性。使用配置管理工具,跟踪代码更改、协作和代码版本控制。 C++ …

    2025年12月18日
    000
  • C++框架中依赖项管理的最佳实践有哪些?

    依赖项管理的最佳实践:使用包管理工具(如 conan、cmake、vcpkg)进行管理。通过版本控制和锁文件控制依赖项版本。隔离依赖项代码以避免冲突。进行测试和验证以确保兼容性。实践案例:使用 conan 管理依赖项。 C++ 框架中的依赖项管理最佳实践 在现代 C++ 开发中,依赖项管理对于管理不…

    2025年12月18日
    000
  • 第三方库集成与C++框架中的依赖项管理

    现代 c++++ 框架中集成第三方库和管理依赖项,至关重要。本文探讨使用 cmake、conan 和 bazel 等工具集成第三方库的方法:cmake: 使用 find_package 命令查找库,并使用 target_link_libraries 命令链接到目标。conan: 使用 conanfi…

    2025年12月18日
    000
  • C++ 框架的性能基准:平衡性能和可维护性

    使用综合性能基准框架比较 c++++ 框架:选择框架:boost.asio、libevent、zeromq运行基准测试:网络服务器、消息队列、数据结构结果:boost.asio 性能最佳,libevent 并行处理更优最佳实践:匹配用例、监控指标、异步编程、优化低效代码 C++ 框架的性能基准:平衡…

    2025年12月18日
    000
  • C++ 框架新手疑惑扫盲:常见问题逐个击破

    对于 c++++ 框架新手,常见问题包括:选择合适的框架:根据需求选择,如 boost(功能库)、qt(gui 框架)、poco(轻量级框架)。使用框架特性:利用框架的 api 和文档,如阅读文档、查看示例代码、加入社区论坛。集成第三方库:使用 cmake、包管理器(如 vcpkg)或手动集成。解决…

    2025年12月18日
    000
  • C++ 框架在性能上的优势与其他语言框架的对比

    c++++ 框架在性能上具有多重优势:零开销抽象、低级内存管理和高效的数据结构和算法。与 java 和 python 框架相比,c++ 框架由于其编译性质和内存控制而更快,与 go 框架类似,但后者具有更好的垃圾回收机制。 C++ 框架在性能上的优势 在现代软件开发中,框架扮演着至关重要的角色。它们…

    2025年12月18日
    000
  • 协作工具对 C++ 框架社区的重要性

    协作工具对 C++ 框架社区的重要性 在当今竞争激烈的软件开发领域,协作对于成功的项目至关重要。对于 C++ 框架社区尤其如此,因为这些框架高度复杂,经常涉及多个贡献者。协作工具通过促进沟通、自动化任务和共享知识,使团队能够有效地协作。 沟通工具 版本控制系统 (VCS),如 Git 或 Subve…

    2025年12月18日
    000
  • 如何在 C++ 框架社区寻求协作成员?

    通过明确项目所需的技能和专业知识,加入 c++++ 社区,利用社交媒体,创建协作成员请求并评估候选人,可以在 c++ 框架社区中找到协作成员,从而显着提高项目的成功机会和开发效率。 在 C++ 框架社区寻找协作成员 引言 在 C++ 框架开发中,协作是取得成功的关键因素。创建一个成功的框架需要各种技…

    2025年12月18日
    000
  • C++ 框架初学者常见问题详解:全面解答你的疑惑

    对于 c++++ 框架初学者,常见的困惑包括:根据项目需求选择合适的框架。遵循文档指南、使用包管理器并管理版本,以集成框架到项目中。通过阅读错误日志、使用调试器和查阅问题追踪器来调试框架问题。了解框架架构、使用钩子点和创建扩展模块来扩展框架功能。保持更新、遵循最佳实践和参与社区,以有效地维护和更新框…

    2025年12月18日
    000
  • C++ 框架的可维护性挑战:保持代码的健康

    c++++ 框架可维护性面临的主要挑战包括:代码库庞大:采用模块化代码和命名空间来组织和简化代码。依赖关系复杂:使用版本控制和依赖项管理工具来跟踪并管理依赖项。api 变更:通过保持更新并使用抽象接口来最小化 api 变更的影响。 C++ 框架的可维护性挑战:保持代码的健康 引言 在 C++ 开发中…

    2025年12月18日
    000
  • C++ 框架版本管理策略:确保代码稳定性和可扩展性

    c++++ 框架版本管理策略通过遵守以下步骤可确保稳定性和可扩展性:使用 c++ package manager (cpm) 管理框架版本和依赖项。应用版本约束以定义框架的兼容版本范围。锁定依赖项版本以确保团队成员使用相同的版本集。实施兼容性测试以识别和解决框架版本更新中的问题。借助 git 版本控…

    2025年12月18日
    000
  • C++ 框架的可移植性瓶颈:跨平台挑战

    跨平台 c++++ 框架的可移植性瓶颈:平台差异(操作系统、体系结构、库)阻碍了 c++ 框架的跨平台部署。跨平台 gui 开发凸显了此问题,需要针对不同平台调整代码。跨平台抽象层 (pal) 提供通用 api,但在性能和功能上可能受到限制。开发人员必须权衡 pal 的便利性与原生 api 的效率,…

    2025年12月18日
    000
  • c语言源代码怎么找

    您可以通过以下方式查找 C 语言源代码:查看开源代码库(如 GitHub、Bitbucket 和 SourceForge);访问特定领域网站(如 LeetCode、HackerRank 和 CodeChef);利用本地资源(如软件包管理系统);查找现成的项目(如第三方 C 语言库);使用搜索引擎(如…

    2025年12月18日
    000
  • 如何选择合适的 C++ 框架进行人工智能开发?

    评估标准:性能:处理密集型 ai 任务的效率灵活性:自定义和扩展性生态系统:社区支持和预建模块文档和支持:集成和故障排除社区:解决问题和共享知识顶级 c++++ ai 框架:tensorflow:社区支持和生态系统pytorch:灵活性caffe2:深度学习任务cntk:大规模分布式训练eigen:…

    2025年12月18日
    000
  • C++ 框架中依赖注入的未来展望

    依赖注入在 c++++ 框架中的未来展望:松散耦合、可重用、可扩展、可测试。流行框架:boost.di、cpp-di、fruit。实战案例:使用 cpp-di 注入文件系统操作系统的依赖项。未来趋势:编译时 di、类型安全 di、领域特定 di 框架。 C++ 框架中依赖注入的未来展望 引言 依赖注…

    2025年12月18日
    000
  • 嵌入式系统中 C++ 框架的选择与实施策略

    在嵌入式系统中选择和实施 c++++ 框架时,应考虑特定领域知识、可扩展性、社区支持等因素。推荐的框架包括 arduino、freertos 和 cubemx。实施策略包括逐步实施、了解框架、自定义配置和版本控制。实战案例展示了 arduino 框架在 led 闪烁项目中的应用。通过遵循这些原则,开…

    2025年12月18日
    000
  • 嵌入式系统 C++ 框架之竞争优势解析

    嵌入式系统 c++++ 框架的竞争优势在于:可复用性:模块化组件可重用,缩短开发时间和成本。可扩展性:易于扩展新功能或修改现有功能,满足系统随时间推移的变化需求。代码质量:强制执行编码风格和最佳实践,提高代码质量和可维护性。性能:针对嵌入式系统优化,提升性能和效率。市场占有率:广泛采用的框架拥有庞大…

    2025年12月18日
    000
  • C++ 框架在微服务架构中的角色

    c++++ 框架在微服务架构中起着至关重要的作用。它们提供强大工具,简化了微服务的开发、部署和维护。c++ 框架的优势包括:高性能低延迟资源效率稳健性流行的 c++ 微服务框架包括 pistachio、katana 和 cpp-netlib。pistachio 示例演示了如何使用该框架创建简单的微服…

    2025年12月18日
    000
  • C++ 框架中使用依赖注入的优势和劣势

    依赖注入 (di) 提升了 c++++ 框架的可测试性和可维护性,通过将依赖项注入对象而不是直接实例化它们。其优势包括易于模拟和测试依赖关系,增强代码可维护性,使类的责任范围更窄。潜在的劣势是性能开销和复杂性的增加。一个在 c++ 中使用的流行 di 框架是 dagger,它允许开发人员定义组件并通…

    2025年12月18日
    000
  • 使用 C++ 框架构建响应式 Web 应用的技巧

    利用 c++++ 框架构建响应式 web 应用的技巧包括:选择响应式框架(例如 boost.beast、cppcms、wt)运用 css media queries 实现响应式样式使用网格系统(例如 bootstrap、foundation)创建响应式布局利用 srcset 属性提供响应式图像 使用…

    2025年12月18日
    000

发表回复

登录后才能评论
关注微信