Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >干货 | 携程火车票7个优化动画性能的方法

干货 | 携程火车票7个优化动画性能的方法

作者头像
携程技术
发布于 2023-09-06 04:59:08
发布于 2023-09-06 04:59:08
45400
代码可运行
举报
文章被收录于专栏:携程技术携程技术
运行总次数:0
代码可运行

作者简介

Kay Huang,携程高级视觉设计师,专注于前端样式与动画领域。

一 、背景

携程火车票营销页使用 css 制作动画很多年了,这大大提高了动画给予页面丰富的视觉体验。不过,在开发的过程中,也遇到了一些性能相关问题和用户反馈,比如头部动画卡顿、页面打开时间较长、页面打开后部分数据加载时间较长等问题。为解决这些问题,我们借助性能检测工具定位问题,并查阅源码、文档等资源解决问题,形成了这篇文章。

二、渲染优化

要优化动画性能,首先要了解浏览器是如何进行元素渲染的,浏览器的渲染流程有以下四步:

a. 计算元素的样式(可能通过脚本重新计算);

b. 生成每个元素的几何形状和位置(布局);

c. 绘制图层的每个像素(初始化绘图并且进行绘图);

d. 将图层绘制到屏幕上(合并渲染层)。

对于 CSS3 动画来说,每一帧都要经历上述过程。关于最后一步合并渲染层(可以类比 Photoshop 的图层),浏览器会在特定的场合创建独立的渲染层,每个渲染层由 GPU 独立绘制,互不影响,最后浏览器再把各个渲染层合并。这是一种代价较低的操作。

理论上说,FPS 越高,动画会越流畅,目前大多数设备的屏幕刷新率为 60 次/秒,所以通常来讲 FPS 为 60frame/s 时动画效果最好,也就是每帧的消耗时间(帧预算)为 16.67ms。

三、解决方案

如上所说浏览器有整理工作要做,因此所有工作需要尽量在 10 ms 内完成。如果制作的动画触发了布局,那就相当于要进行第二步重新绘制,如果重新绘制的话浏览器渲染的时间肯定超过 16ms,那么我们的页面就会出现卡顿,如果是移动端的话那就会更慢,所以我们如果要优化的话那就要从第一步直接跳到第四步。

下面我写了七种优化动画性能的方法,有直接从第一步跳到第四步的也有一些其他平时优化注意事项。

3.1 开启 GPU 加速

Transform 属性可以向元素应用 2D 或者 3D 转换,可以对元素进行选择、缩放、移动和倾斜。

在日常中我们可以使用 left/top,translate 来实现元素的位移,但是其实性能上还是有一定区别的因为 transform 属性不会改变自己和他周围元素的布局,他会对元素的整体产生影响。

让我们先用 top/left 属性创建一个动画看看效果。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<style>
      .heart{animation: heartbeat 4s infinite;width:50px;height:50px;background:red;position:absolute;left:30px;top:30px;}
      @keyframes heartbeat{
          0%{top:30px;left:30px;}
          25%{top:30px;left:230px;}
          50%{top:230px;left:230px;}
          75%{top:230px;left:30px;}
      }
</style>

用 chrome 浏览器的 DevTools 查看可以看到红色方块都是布局重绘。

图中有那么多的红色方框与帧数是因为浏览器会做大量的计算,动画就会卡顿。

因为每一帧的变化浏览器都在进行布局、绘制、把新的位图交给 GPU 内存,虽然只改变元素位置但是很可能要同步改变他的子元素的位置,那浏览器就要重新计算布局,计算完后主线程再来重新生成该元素的位图。

现在,将动画用 transform 代替:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<style>
      .heart{animation: heartbeat 1s;width:50px;height:50px;background:red;}
      @keyframes heartbeat{
          0%{transform: translate(30px,30px);}
     25%{transform: translate(30px,230px);}
       50%{transform: translate(230px,230px);}
          75%{transform: translate(230px,30px);}
      }
</style>

再次分析,可以看到,没有发生红色的重绘方块且只有一条帧数,就知道动画肯定会流畅丝滑。

因为 transform 属性不会改变自己和他周围元素的布局,他会对元素的整体产生影响。

我们通过节点的 transform 可以修改节点的位置、旋转、大小等。我们平常会使用 left 和 top 属性来修改节点的位置,但正如上面所述,left 和 top 会触发重布局,修改时的代价相当大。取而代之的更好方法是使用 translate,这个不会触发重布局。

3.2 避免使用影响性能的 CSS 属性

这些属性会影响性能,因为它们需要进行复杂的计算和渲染,尤其是在动画中使用时。这些属性可能会导致浏览器进行重排和重绘,从而影响页面的性能和流畅度。

如果您必须使用这些属性,请尽可能减少它们的使用。例如,您可以尝试使用 CSS3 的 transform 属性来实现 box-shadow 和 border-radius 的效果,因为它们可以更好地利用浏览器的硬件加速。

例如,下面是一个使用 box-shadow 属性的示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
.box {
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}

这个 box-shadow 属性会在元素周围添加一个阴影效果,但是它会影响性能,因为浏览器需要进行复杂的计算和渲染。为了优化性能,我们可以使用 CSS3 的 transform 属性来实现相同的效果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
.box {  transform: translateZ(0);  box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);}

这个 transform 属性会启用硬件加速,从而提高性能。同时,我们仍然可以使用 box-shadow 属性来添加阴影效果。

3.3 避免使用复杂的选择器

选择器和动画之间存在一定的关系。在 CSS 动画中,选择器的复杂度越高,样式计算的时间就越长。在动画中使用复杂的选择器会导致浏览器需要更长的时间来计算样式,从而影响动画的性能和流畅度。

例如,当我们使用复杂的选择器来选择元素,并为它们添加动画效果时,浏览器需要花费更长的时间来计算样式,从而影响动画的性能和流畅度。相反,当我们使用简单的选择器来选择元素,并为它们添加动画效果时,浏览器可以更快地计算样式,从而提高动画的性能和流畅度。

假设我们有一个列表,其中包含多个项目。我们想要为这些项目添加一个简单的动画效果,当鼠标悬停在项目上时,项目的背景色会渐变为蓝色。我们可以使用以下 CSS 代码来实现这个效果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/* 使用类选择器来选择所有项目 */
.item {
  background-color: #fff; /* 初始背景色为白色 */
  transition: background-color 0.3s ease; /* 添加背景色渐变动画 */
}

/* 当鼠标悬停在项目上时,将背景色渐变为蓝色 */
.item:hover {
  background-color: #007bff; /* 背景色渐变为蓝色 */
}

在这个例子中,我们使用了类选择器来选择所有的项目,并为它们添加了一个初始的背景色和一个背景色渐变动画。当鼠标悬停在项目上时,我们使用: hover 伪类选择器来选择当前悬停的项目,并将其背景色渐变为蓝色。

这个例子中的选择器非常简单,浏览器可以很快地计算样式,从而提高动画的性能和流畅度。相比之下,如果我们使用复杂的选择器来选择项目,并为它们添加动画效果,浏览器需要花费更长的时间来计算样式,从而影响动画的性能和流畅度。

3.4 使用 will-change

使用 will-change 属性来告诉浏览器哪些元素将要进行动画,以便浏览器提前进行优化。

will-change 属性是 CSS3 的一个新属性,它可以告诉浏览器哪些元素将要进行动画,从而使浏览器可以提前进行优化,提高动画的性能和流畅度。

例如,如果您要对某个元素进行动画,您可以在 CSS 中添加以下代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#textbox {
  opacity: 1; /* 初始透明度为1 */
  transition: opacity 0.3s ease; /* 添加透明度渐变动画 */
  will-change: opacity; /* 告知浏览器我们将会修改透明度 */
}

在这个例子中,我们使用 will-change 属性来告知浏览器我们将会修改文本框的透明度,从而使浏览器可以提前进行优化。当动画开始时,浏览器已经准备好了相应的资源,从而可以更快地渲染动画,提高动画的性能和流畅度。

需要注意的是,will-change 属性应该谨慎使用,因为它可能会导致浏览器提前分配额外的内存和资源,从而影响页面的性能。因此,只有在必要的情况下才应该使用 will-change 属性。

CSS3 will-change 属于 web 标准属性,兼容性这块 Chrome/FireFox/Opera 都是支持的。

使用 will-change 属性是优化 CSS 动画的重要技巧之一,可以提高动画的性能和流畅度。

3.5 使用 requestAnimationFrame

requestAnimationFrame 代替 setTimeout 或 setInterval 来执行动画,因为它可以最大程度地利用浏览器的优化。

requestAnimationFrame 是浏览器提供的一个 API,它可以让我们在下一次浏览器绘制之前执行动画。与 setTimeout 或 setInterval 相比,requestAnimationFrame 可以更好地利用浏览器的优化,从而提高动画的性能和流畅度。

例如,如果您要对某个元素进行动画,您可以使用 requestAnimationFrame 来执行动画:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function animate() {
  // 更新元素的样式
  element.style.transform = 'translateX(100px)';

  // 使用requestAnimationFrame执行下一帧动画
  requestAnimationFrame(animate);
}

// 开始执行动画
requestAnimationFrame(animate);

在上面的代码中,我们使用 requestAnimationFrame 来执行动画。在每一帧动画中,我们更新元素的样式,然后使用 requestAnimationFrame 执行下一帧动画。这样可以最大程度地利用浏览器的优化,提高动画的性能和流畅度。

需要注意的是,requestAnimationFrame 并不是所有浏览器都支持,因此在使用它时需要进行兼容性处理。通常情况下,我们可以使用一个polyfill来实现 requestAnimationFrame 的兼容性。

3.6 避免在动画中使用 JavaScript 操作 DOM

在动画中使用 JavaScript 操作 DOM 会影响性能,主要是因为 DOM 操作是非常耗费资源的,因为这会引起重排和重绘。每次操作 DOM 都会触发浏览器重新计算元素的布局和重新绘制元素,这些操作会消耗大量的 CPU 资源和内存,导致动画卡顿或者不流畅。

在动画中,如果需要频繁地操作DOM,就会导致性能问题。例如,如果在动画中使用 JavaScript 来改变元素的位置、尺寸、样式等属性,就会触发 DOM 操作,影响动画的流畅度。

如果必须使用 JavaScript 操作 DOM,请尽可能减少它们的使用。例如,您可以在动画开始前将需要操作的元素缓存到变量中,然后在动画中直接使用这些变量,而不是每次都重新查找元素。

另外,还可以使用 CSS3 的动画属性来代替 JavaScript 操作 DOM。例如,使用 animation 属性可以实现复杂的动画效果,而不需要使用 JavaScript 操作 DOM,下面会详细说为什么用尽量用 css 动画而不使用 javascript 动画。

3.7 用 CSS 动画尽量不使用 JavaScript 动画

因为前者可以更好地利用浏览器的优化。

假设我们有一个按钮,当用户点击按钮时,我们想要将一个文本框从屏幕上移除,并在移除时添加一个简单的动画效果。我们可以使用以下 JavaScript 代码来实现这个效果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var textbox = document.getElementById('textbox'); // 获取文本框元素
var button = document.getElementById('button'); // 获取按钮元素

button.addEventListener('click', function() {
  textbox.style.opacity = 0; // 文本框透明度渐变为0
  setTimeout(function() {
    textbox.parentNode.removeChild(textbox); // 移除文本框元素
  }, 300); // 延迟300毫秒后移除文本框元素
});

在这个例子中,我们使用 JavaScript 操作 DOM 元素,通过获取文本框和按钮元素,并在按钮被点击时逐渐将文本框的透明度降低到 0,然后在 300 毫秒后移除文本框元素。

然而,这种方法会导致浏览器进行重排和重绘,从而影响动画的性能和流畅度。相反,我们可以使用 CSS3 的 transition 属性来实现一个简单的动画效果,而无需使用 JavaScript 操作 DOM 元素。

例如,我们可以使用以下 CSS 代码来实现一个简单的动画效果,当用户点击按钮时,文本框会逐渐消失:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#textbox {
  opacity: 1; /* 初始透明度为1 */
  transition: opacity 0.3s ease; /* 添加透明度渐变动画 */
}

#textbox.hide {
  opacity: 0; /* 透明度渐变为0 */
}

在这个例子中,我们使用 CSS3 的 transition 属性来实现一个简单的透明度渐变动画。当用户点击按钮时,我们使用 JavaScript 为文本框添加一个 hide 类,这个类会将文本框的透明度逐渐降低到 0,从而实现文本框逐渐消失的动画效果。

这个例子中的动画效果可以直接作用于 DOM 元素,而无需使用 JavaScript 操作 DOM 元素,从而提高动画的性能和流畅度。

在动画中使用 CSS 动画可以更好地利用浏览器的硬件加速,从而提高动画的性能和流畅度。相比之下,JavaScript 动画通常需要更多的计算和操作,从而影响动画的性能和流畅度。

当然,在某些情况下,JavaScript 动画可能是必要的。例如,在需要与用户交互的动画中,JavaScript 动画可以更好地控制动画的行为。但是,在这种情况下,我们仍然应该尽可能减少 JavaScript 操作的次数,以提高动画的性能和流畅度。

四、结论

动画给予了页面丰富的视觉体验。我们应该尽力避免使用会触发重布局和重绘的属性,以免失帧。最好提前申明动画,这样能让浏览器提前对动画进行优化。由于 GPU 的参与,现在用来做动画的最好属性是如下几个:* opacity* translate* rotate* scale,Javascript 优化、减少 Layout 和 Paint。希望对大家了解浏览器的渲染机制和日常的动画开发有所帮助。

性能优化是一件不断持续,不断深入的事情。我们通过本文中所介绍的改进措施对页面性能实现了很大的优化,达到了不错的效果。后续也会在此基础之上对还可提高的地方继续加深,后续提供通用的解决方案。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-06-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 携程技术中心 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
盒子端 CSS 动画性能提升研究
不同于传统的 PC Web 或者是移动 WEB,在腾讯视频客厅盒子端,接大屏显示器(电视)下,许多能流畅运行于 PC 端、移动端的 Web 动画,受限于硬件水平,在盒子端的表现的往往不尽如人意。 基于此,对于 Web 动画的性能问题,仅仅停留在感觉已经优化的OK之上,是不够的,想要在盒子端跑出高性能接近 60 FPS 的流畅动画,就必须要刨根问底,深挖每一处可以提升的方法。 流畅动画的标准 理论上说,FPS 越高,动画会越流畅,目前大多数设备的屏幕刷新率为 60 次/秒,所以通常来讲 FPS 为 60fra
Sb_Coco
2018/05/28
8210
盒子端 CSS 动画性能提升研究
对于 Web 动画的性能问题,仅仅停留在感觉已经优化的OK之上,是不够的,想要在盒子端跑出高性能接近 60 FPS 的流畅动画,就必须要刨根问底,深挖每一处可以提升的方法。
Sb_Coco
2018/01/15
2.3K9
盒子端 CSS 动画性能提升研究
疯狂操作 CSS3 实现 60 FPS 动画效果,CodeReview 时同事直呼:细节!
通常来讲,当动画的每秒帧数低于 12 (即 12 FPS 以下)时,我们的大脑就能快速从动画中区分出一些静止的图片,所以此时的动画并不是无缝动画。
掘金安东尼
2022/09/22
5790
CSS动画的性能优化
在Web页面中使用动画效果已经不是什么稀奇的事情了。但凡优秀的UI界面都会有一些点缀用的动画效果。举个例子,Stripe Checkout小组通过UI动画效果来增强支付体验。
mmzhou
2018/08/06
2K0
CSS动画的性能优化
深度剖析浏览器渲染性能原理,你到底知道多少
作者:齐修_qixiuss https://www.jianshu.com/p/a32b890c29b1
用户4456933
2021/06/01
1.6K0
深度剖析浏览器渲染性能原理,你到底知道多少
JavaScript是如何工作的: CSS 和 JS 动画底层原理及如何优化它们的性能
你肯定知道,动画在创建引人注目的 Web 应用程序中扮演着重要的角色。随着用户越来越多地将注意力转移到用户体验上,商户开始意识到完美、愉快的用户体验的重要性,结果 Web 应用程序变得越来越重,并具有更动态交互的 UI。这一切都需要更复杂的动画,以便用户在整个过程中更平稳地进行状态转换。今天,这甚至不被认为是什么特别的事情。用户正变得越来越挑剔,默认情况下,他们期望的是具有高响应性和交互性的用户界面。
Javanx
2019/10/14
3.8K0
JavaScript是如何工作的: CSS 和 JS 动画底层原理及如何优化它们的性能
分享 | 前端性能优化(CSS动画篇)
最近拜读了一下html5rocks上几位大神写的一篇关于CSS3动画性能优化的文章,学到了很多,在这里记录一下,其中的知识都是来源于这俩篇文章,我只是截取了其中比较关注的内容出来,原文地址High Performance Animations及Accelerated Rendering in Chrome
疯狂的技术宅
2019/03/28
2.1K0
前端动画实现总结
SVG动画由SVG元素内部的元素属性控制,一般通过一下几个元素控制: - 用于控制动画延时 - 对属性的连续改变进行控制 - 颜色变化,但用就能控制 - 控制如缩放、旋转等几何变化 - 控制SVG内元素的移动路径
江米小枣
2020/06/16
1.5K0
进阶|你的css经不住这层考验,就是失败...
前端爱好者的知识盛宴 今天的技术提供者是鹅厂的chokcoco. chokcoco是一位用css用得贼6的大神. 文末会有他的博客链接... 欢迎各位前端爱好者去他博客游玩下... 供稿者认为仅仅... 在PC 端、移动端的 Web 动画... 还需要经得住在盒子端的考验! 甚至达到60 FPS的快感... 跟着供稿者的思路... 你会锻炼出一种解决问题的方法论... 欢迎留言、转发! 以及提问供稿者! 马上去片! 流畅动画的标准 理论上说,FPS 越高,动画会越流畅... 目前大多数设备的屏幕刷新率为
用户1097444
2022/06/29
7410
进阶|你的css经不住这层考验,就是失败...
浏览器层面优化前端性能(2):Reader引擎线程与模块分析优化点
renderer与DOM元素是相对应的,但并不是一一对应,有些DOM元素没有对应的renderer,而有些DOM元素却对应了好几个renderer,对应多个renderer的情况是普遍存在的,就是为了解决一个renderer描述不清楚如何显示出来的问题,譬如有下拉列表的select元素,我们就需要三个renderer:一个用于显示区域,一个用于下拉列表框,还有一个用于按钮。
周陆军博客
2023/04/09
1.3K0
制作60fps的高性能动画
说到web的高性能动画,这部分内容其实已经是老生常谈的了,不过其中还是有不少比较新的而且非常实用的内容可以和大家分享一下。
QQ音乐前端团队
2018/09/25
2.9K2
Web动画性能介绍
帧率(FPS):描述每秒播放的帧数,单位为 Hz 或者 frame/s (帧/秒)。
前端GoGoGo
2018/08/27
9490
Web动画性能介绍
H5 APP开发中的性能优化
H5 APP的性能优化是提升用户体验的关键,尤其是在移动端,性能问题会直接影响用户留存率。以下是H5 APP开发中常见的性能优化策略。
数字孪生开发者
2025/02/25
2960
H5 APP开发中的性能优化
使用CSS3实现60FPS的移动端动画(转)
如果您按照我们的提示,您在移动应用程序中使用动画元素会很容易,在其中适当地使用动画元素也会很容易...
山河木马
2019/03/05
2K0
使用CSS3实现60FPS的移动端动画(转)
浏览器渲染之回流重绘
回流和重绘是前端开发的高频词汇之一,你可以在各种面经,性能优化相关文章可以看到,但是很多都是草草带过。本文带你从浏览器渲染流程中了解回流与重绘的原理。
政采云前端团队
2021/09/30
1.9K0
浏览器渲染之回流重绘
CSS动画与GPU
那么问题是:已经小心遵守这些规则了,为什么动画还会卡顿、跳帧?还能优化吗?要从哪里入手?
ayqy贾杰
2023/03/15
2.7K0
CSS动画与GPU
【前端性能优化】深入解析重绘和回流,构建高性能Web界面
在Web浏览器的工作流程中,回流是一个关键步骤,它发生在浏览器需要根据DOM元素的尺寸、位置或某些视觉属性变化来重新计算元素的布局情况时。具体来说,当一个元素的几何属性改变,比如宽度、高度或者隐藏/显示状态变动,浏览器执行以下步骤:
空白诗
2024/06/14
5200
【前端性能优化】深入解析重绘和回流,构建高性能Web界面
每天10个前端小知识 【Day 16】
改变transform或opacity不会触发浏览器重新布局(reflow)或重绘(repaint),只会触发复合(compositions)。
程序媛夏天
2024/01/18
2980
每天10个前端小知识 【Day 16】
浏览器页面渲染全解析过程优化及实战指南详解
将HTML、CSS和JavaScript转换为屏幕上的像素,实现用户可交互的视觉界面。
小焱
2025/05/22
4960
浏览器页面渲染全解析过程优化及实战指南详解
提高JavaScript动画的性能
在本文中,我收集了一些开发技巧,以帮助您解决JavaScript动画的性能问题,并使您更容易实现在web上实现流畅移动的60fps(每秒帧数)目标。 1、避免使用昂贵的CSS属性 你是否打算使用CSS动画CSS属性转换/ CSS关键帧或JavaScript,重要的是要知道哪些属性带来的改变页面的几何(布局)——这意味着页面上的其他元素的位置将会重新计算,或将涉及绘画操作。布局和绘制任务对于浏览器来说都是非常昂贵的,特别是当你的页面上有几个元素时。因此,如果您避免对触发布局或绘制操作的CSS属性进行动画化,
程序你好
2018/07/20
2.3K0
相关推荐
盒子端 CSS 动画性能提升研究
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档