使用CSS3实现60FPS的移动端动画(转)
如果您按照我们的提示,您在移动应用程序中使用动画元素会很容易,在其中适当地使用动画元素也会很容易...
虽然每个人都在移动领域使用CSS3动画,但是很多人做的并不正确。开发人员经常无视最佳做法。这是因为人们不了解这些做法存在的原因,以及为什么这些做法会得到强烈认可。
设备规格范围广泛,因此如果您不优化您的代码,很大程度上将会提供一个次级体验。
请记住:一些高端旗舰设备推动外壳的发展,但世界上大多数使用的设备类型与这些规格怪物相比,看起来更像一个带有液晶显示屏的算盘。
我们想帮助并且给予您正确使用CSS3的力量。要做到这一点,首先要了解一些事情。
了解时间线
浏览器在渲染和播放元素时执行什么操作?该时间轴称为关键渲染路径:
要实现平滑的动画,我们需要关注的是改变影响复合步骤的属性,而不是将此压力添加到以前的图层。
1.样式
浏览器开始计算应用于元素的样式 - 重新计算样式。
2.布局
在下一层中,浏览器生成每个元素的形状和位置 - 布局。也就是浏览器设置页面属性,如width和height,以及它的margin或left/top/right/bottom。
3.着色
浏览器将每个元素的像素填充到图层中。指的是这些属性:box-shadow,border-radius,color,background-color等。
4.合成
这是您要执行动画的地方,因为浏览器会将所有图层拖到屏幕上。
现代浏览器可以很好的支持四种动画风格的属性,使用transform和opacity属性来制作。
- 位置 - transform:translateX(n)translateY(n)translateZ(n);
- 缩放 - transform:scale(n);
- 旋转 - transform:rotate(ndeg);
- 不透明度 - opacity:n;
如何实现每秒60帧
考虑到这一点,现在是时候卷起袖子工作了。
我们从HTML开始吧。我们将创建一个非常简单的结构,并将我们的应用程序菜单放在布局类中。
<div class="layout">
<div class="app-menu"></div>
<div class="header">
<div class="menu-icon"></div>
</div>
</div>
错误的方法是这样的
.app-menu {
left: -300px;
transition: left 300ms linear;
}
.app-menu-open .app-menu {
left: 0px;
transition: left 300ms linear;
}
看到我们改变的属性了吗?你应该避免使用属性的left/top/right/bottom进行转换。那些不会创建流畅的动画,因为它们强制浏览器每次执行布局传递,影响所有子元素。
结果是这样的:
这个动画不太顺利。我们检查了DevTools Timeline,看看发生了什么事情,结果是这样的:
绿色区域表示渲染动画花费的时间。
该数据呈现不规则的帧率和缓慢的性能。
“绿色条表示FPS。高一点的表示动画呈现为60 FPS。低一点的表示低于60 FPS。因此,理想情况下,您希望绿色栏在时间轴上始终保持高位。那些红色的条也显示出一个尾巴,所以,另一种方式来衡量你的进步是消除那些红色的尾巴。”
使用变换
.app-menu {
-webkit-transform: translateX(-100%);
transform: translateX(-100%);
transition: transform 300ms linear;
}
.app-menu-open .app-menu {
-webkit-transform: none;
transform: none;
transition: transform 300ms linear;
}
transform属性影响的是复合步骤,而不是布局。在这里,我们通知浏览器:我们的图层在动画开始之前是稳定的,所以我们在渲染动画时遇到更少的停顿。
这正是Timeline所反映的:
结果开始变得更好了,帧率似乎也已经稳定,因此,动画运行也平稳了起来。
在GPU中运行动画
那我们继续吧。要真正让它运行顺利,我们将使用GPU渲染动画。
.app-menu {
-webkit-transform: translateX(-100%);
transform: translateX(-100%);
transition: transform 300ms linear;
will-change: transform;
}
虽然一些浏览器仍然需要translateZ()或translate3d()作为回调,will-change属性是未来。此属性将元素提升到另一层,因此浏览器不必考虑布局渲染或绘画。
看看是不是更顺利了?这是时间线的证明:
动画的帧率更加恒定,呈现的也更快。但是开始的时候还是有一长串的架构:起初有点瓶颈。
还记得我们在开始创建的HTML结构吗?我们来看看我们是如何在JavaScript中控制app-menudiv:
function toggleClassMenu() {
var layout = document.querySelector(".layout");
if(!layout.classList.contains("app-menu-open")) {
layout.classList.add("app-menu-open");
} else {
layout.classList.remove("app-menu-open");
}
}
var oppMenu = document.querySelector(".menu-icon");
oppMenu.addEventListener("click", toggleClassMenu, false);
啊哈!问题是由我们将类添加到layout来引起的。这迫使浏览器重新生成我们的样式表,并且影响了渲染性能。
像黄油溶液一样流畅的60FPS
如果我们在视口区域外创建菜单怎么办?将菜单放在一个孤立的区域将确保我们只影响我们希望动画的元素。
所以,我们提出以下HTML结构:
<div class="menu">
<div class="app-menu"></div>
</div>
<div class="layout">
<div class="header">
<div class="menu-icon"></div>
</div>
</div>
现在我们必须以略微不同的方式来控制菜单的状态。在动画结束时,我们将通过使用JavaScript中的函数来操作我们删除的transitionend函数中的动画。
function toggleClassMenu() {
myMenu.classList.add("menu--animatable");
if(!myMenu.classList.contains("menu--visible")) {
myMenu.classList.add("menu--visible");
} else {
myMenu.classList.remove("menu--visible");
}
}
function OnTransitionEnd() {
myMenu.classList.remove("menu--animatable");
}
var myMenu = document.querySelector(".menu");
var oppMenu = document.querySelector(".menu-icon");
myMenu.addEventListener("transitionend", OnTransitionEnd, false);
oppMenu.addEventListener("click", toggleClassMenu, false);
myMenu.addEventListener("click", toggleClassMenu, false);
让我们一起来看看结果。这是一个完整的完全启用CSS3的示例,其中的所有内容都在正确的位置:
.menu {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: hidden;
pointer-events: none;
z-index: 150;
}
.menu--visible {
pointer-events: auto;
}
.app-menu {
background-color: #fff;
color: #fff;
position: relative;
max-width: 400px;
width: 90%;
height: 100%;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.5);
-webkit-transform: translateX(-103%);
transform: translateX(-103%);
display: flex;
flex-direction: column;
will-change: transform;
z-index: 160;
pointer-events: auto;
}
.menu--visible .app-menu {
-webkit-transform: none;
transform: none;
}
.menu--animatable .app-menu {
transition: all 130ms ease-in;
}
.menu--visible.menu--animatable .app-menu {
transition: all 330ms ease-out;
}
.menu:after {
content: '';
display: block;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.4);
opacity: 0;
will-change: opacity;
pointer-events: none;
transition: opacity 0.3s cubic-bezier(0,0,0.3,1);
}
.menu--visible.menu:after {
opacity: 1;
pointer-events: auto;
}
那么我们看到的时间线是怎样的呢?
每天都是绿色条,。想看一个实例吗?点击这里(http://codepen.io/Onyros/pen/jAJxkW)。
- 小程序组件化框架 WePY 在性能调优上做出的探究
- go sync.Mutex 设计思想与演化过程 (一)
- HTTPS 原理浅析及其在 Android 中的使用
- Bugly 多渠道热更新解决方案
- Go发起Http请求及获取相关参数
- Swift 对象内存模型探究(一)
- 关于 Block 中捕获 self 的分析
- go语言base64加密解密的方法
- Android 减包 - 减少APK大小
- Android 插件技术实战总结
- Golang语言社区--【基础知识】常量
- Android GC 原理探究
- 舞动的表情包——浅析GIF格式图片的存储和压缩
- go语言的官方包sync.Pool的实现原理和适用场景
- HTML 教程
- HTML 简介
- html div 标签介绍
- html span 标签介绍
- html a 超链接标签
- HTML Br换行标签介绍
- HTML P段落标签介绍
- HTML br与p标签区别
- Html H 标题标签
- html px em pt长度单位
- HTML form 标签
- HTML radio 单选框
- HTML B 加粗标签
- HTML strong加粗粗体标签
- HTML em 强调标签
- HTML i 斜体标签
- HTML u下划线标签
- HTML s 删除线标签
- Html img 图片标签
- Html上标注sup与下标注sub标签
- HTML nobr 禁止换行标签
- HTML hr 水平线标签
- HTML label 标签
- HTML input 标签
- HTML textarea 标签
- HTML select下拉列表标签
- HTML checkbox 多选框
- HTML font color 标签
- HTML iframe 框架标签
- HTML Table 表格
- HTML dl dt dd 标签
- HTML ol li有序列表标签
- HTML ul li 无序列表标签
- HTML 注释
- CSS 教程
- CSS 简介
- CSS 语法
- CSS Id 和 Class选择器
- CSS 样式的创建
- CSS background 背景介绍
- CSS 文本样式
- CSS font 字体
- CSS A 链接
- CSS ul ol列表样式
- CSS TABLE 样式
- CSS 框模型
- CSS border 边框
- CSS Outlines 轮廓
- CSS 外边距 Margin
- CSS Padding 内边距
- CSS 分组和嵌套选择器
- CSS 尺寸 (Dimension)
- CSS Display 属性
- CSS Position 定位
- CSS Float 浮动
- CSS 水平对齐(Horizontal Align)
- CSS 组合选择符
- CSS 伪类
- CSS 伪元素
- CSS 导航栏
- CSS 下拉菜单
- CSS 图片廊
- CSS 图像透明/不透明
- CSS sprite 图像拼合技术
- CSS 媒体类型
- CSS 属性选择器
- CSS 实例
- leetcode树之二叉树的深度
- PowerBI DAX 库存余量模型与计算
- 20种小技巧,玩转Google Colab
- 图深度学习入门教程(九)——图滤波神经网络模型
- 技术分享 | 我的内存去哪儿?生产实践
- 数据传输 | DTLE 3.20.09.0 来啦!
- R语言对巨灾风险下的再保险合同定价研究案例:广义线性模型和帕累托分布Pareto distributions分析
- 精解四大集合框架:Set核心知识总结
- NeurIPS 2020 | 一种崭新的长尾分布下分类问题的通用算法
- 精解四大集合框架:Map核心知识总结
- 厉害了,Matplotlib还能这样画散点图!
- 20种小技巧,玩转Google Colab
- 不用try catch,如何机智的捕获错误
- StyleGAN2玩出新高度!从华盛顿到特朗普,无缝切换生成历届美国总统
- 深入理解MySQL中事务隔离级别的实现原理