避免无用的渲染绘制(Avoiding Unnecessary Paints)
本文翻译自html5rock上的文章,文章英文原版地址在最后给出。
文中的Paints我翻译成渲染绘制,我自己是这么理解。
开始
绘制(渲染)一个网站或者一个应用的元素对浏览器来说开销是很大的,它会对运行时的效率产生负面影响,在这篇文章中我们将快速的过一遍,哪些情况会导致导致绘制事件在浏览器中产生,以及如何在你今后的工作中尽量避免没必要的绘制。
绘制(渲染):一场超快的旅行
浏览器的主要任务之一就是将DOM和CSS转换成像素并绘制到屏目上,这是一系列复杂的处理过程。浏览器先读取HTML标签并由此创建DOM树,它对CSS也是进行了类似的工作,读取CSS并创建CSSOM树,然后将两者合并,最终我们就可以根据合并后的结构渲染成像素到屏目了
绘制过程本身就挺有趣。在Chrome浏览器中,合并后的DOM树与CSS树被一款名叫Skia的软件进行栅格化。如果你曾使用过CANVAS的API,那么你会觉得它们的API非常相似。
不光是moveTo, lineTo等这些API,另外的一些高级API也一样非常相似。本质上来讲,所有需要被绘制的元素都将被提取到能被Skia执行的集合中,执行后输出的是一堆位图。这些位图将被上传到GPU中,GPU将帮他们组合在一起并最终输出到屏目上。
Skia的工作量是直接受你在元素上所应用的样式引响的。如果你在元素应用的样式算法很复杂那么,会大大加重Skia的工作。你可以参考这篇文章article on how CSS affects page render weight,以更深的理解CSS如何影响页面渲染。
总而言之,绘制工作费时间,如果我们不减少绘制,那么可能会掉侦。用户可能会注意到掉帧,看起来会闪一下。这对于我们的APP上来说是从根本上伤害了用户体验。我们不希望看到这样的结果吧,so让我们来看看哪些东西会产生必要的绘制(渲染)工作,以及我们能对这些做些啥优化。
Scrolling(滚动)
无论你是往上还是往下滚动,内容在显示到屏目上之前浏览器都需要进行重绘。如果一切顺利的话,可能产生重绘的区域会是很小一块,但是即使是很小一块,那一小块元素可能就是应用了复杂的CSS样式。所以不会因为绘制的区域小而绘制的速度会快。
为了看清哪些区域被重绘了,你可以使用Chrome中自带的调试工具,点击右上角的设置按钮,选中 “Show Paint Rectangles”后,在你的页面中做一些简单的交互,你便会看到一些会闪动的矩形框,那就是重绘的区域了。
滚动的性能表现,是你网站成功的关键。用户真的会关心你的站点或应用滚动的是不是顺畅,他们可不会喜欢滚动的不流畅的网站。我们在滚动时保证轻量的绘制工作,因此而得到的一个好处就是用户看不到闪动或掉帧这类事情了。
我之前已经写过一篇文章是关于滚动性能的,如果你想了解更我,可以参考这篇文章 article on scrolling performance
Interactions(交互)
交互是另一个产生绘制工作的原因,如:hovers, click,touches drags无论用户执行了其中的哪一样操作都会引发绘制或重绘。让我们以hover举个栗子,当hover某个元素时,Chrome不得不重绘那个被hover影响的元素。如果滚动时有一个很大很复杂的重绘工作,那么你将会看到绘制帧频的下降。
大家都想要好的、流畅的交互动画,这咱又得关心一下动画样式在变化时的花费时间及性能成本
An unfortunate combination(不幸的组合)
当我滚动的同时移动鼠标时会发生什么 ?在无意中是完全有可能触发昂贵的重绘开销的,这将导致我的帧频率小于16.7ms(我们应该保持在每秒60帧的频率)。我已经写了一个demo来更直观的表达我所说的情况created a demo 希望你在滚动的同时移动鼠标能看到hover效果。但是让我们看看Chrome调试工具告诉了我们什么
在上图中你可以看到,当我在某一个块元素上(blocks)上hover时调试工具已捕获了绘制工作。为了看效果,我在demo中疯狂的加重了样式效果(缩放,阴间等动画效果)。这导致帧频逼近或偶尔间超过了帧频的临界值。最后我想要的是减少不必要的绘制工作,尤其是在滚动时。
我们如何实现呢,实现其实很简单,技巧是添加一个scroll回调handler处理函数,在这个函数内禁止hover效果,同时设置一个计时器,用以恢复hover效果。这意谓着我们保证在滚动时禁止一些开销昂贵的交互效果,并且在停止滚动足够的时间后恢复那些效果
实际应用时注意!
改变此项会影响你应用程序用户体验,所以明智的对待它,延时恢复效果要在你和的团队能接受的时间范围内
这是对应的代码
// Used to track the enabling of hover effects
var enableTimer = 0; /*
* Listen for a scroll and use that to remove
* the possibility of hover effects
*/
window.addEventListener('scroll', function() {
clearTimeout(enableTimer);
removeHoverClass(); // enable after 1 second, choose your own value here!
enableTimer = setTimeout(addHoverClass, 1000);
}, false); /**
* Removes the hover class from the body. Hover styles
* are reliant on this class being present
*/
function removeHoverClass() {
document.body.classList.remove('hover');
} /**
* Adds the hover class to the body. Hover styles
* are reliant on this class being present
*/
function addHoverClass() {
document.body.classList.add('hover');
}
如你所见,我们用了一个class来决定hover效果是否被允许使用,下面就是这个class的css表达式
/* Expect the hover class to be on the body
before doing any hover effects */
.hover .block:hover {
…
}
这就是所有的内容了
Conclusion(结束语)
渲染的性能表现对于用户是否喜欢你的应用至关重要,你需要的是尽量保证绘制工作量保持在16ms帧频率以下,为了帮助实现这一目标,你得使调式工具一直贯穿于你的开发过程中,确保帧频保持在正常范围内,并随时修复上升的帧频。
被忽略的交互过程,特别是重试绘制元素,是渲染性能的杀手,正如你所见,我们可以用一些简单的代码解决掉这些问题。
看一看你的站点和应用,能不能做一些渲染绘制上面的优化
本文翻译自:
http://www.html5rocks.com/en/tutorials/speed/unnecessary-paints/
我英文水平有限,凑合着翻,全当自我学习欢迎交流学习
========================================================
转载处请注明:博客园(王二狗)willian12345@126.com
避免无用的渲染绘制(Avoiding Unnecessary Paints)的更多相关文章
- Cocos2d-x 学习笔记(25) 渲染 绘制 Render
[Cocos2d-x]学习笔记目录 本文链接:https://www.cnblogs.com/deepcho/p/cocos2dx-render.html 1. 从程序入口到渲染方法 一个Cocos2 ...
- CSS性能优化的8个技巧
本文作者:高峰,360奇舞团前端工程师,W3C性能工作组成员,同时参与WOT工作组的学习. 我们都知道对于网站来说,性能至关重要,CSS作为页面渲染和内容展现的重要环节,影响着用户对整个网站的第一体验 ...
- QML的渲染方式相较于之前的版本也有了重大的更新(CPU线程负责绘制,GPU线程负责渲染),还有好多经常评论 good
作者:qyvlik链接:http://www.zhihu.com/question/38867614/answer/78583440来源:知乎著作权归作者所有,转载请联系作者获得授权. 做UI啊.如果 ...
- 渲染、render与绘制
渲染是抽象到具体的过程: 抽象:图片信息的描述(比如一条线:两个端点的位置.线粗.颜色等特征): 具体:依据抽象信息得到的可视图片(绘制过程). 渲染是中文翻译的问题,有种添油加醋的感觉.直意就是交与 ...
- 源码分析篇 - Android绘制流程(二)measure、layout、draw流程
performTraversals方法会经过measure.layout和draw三个流程才能将一帧View需要显示的内容绘制到屏幕上,用最简化的方式看ViewRootImpl.performTrav ...
- Quartz2D复习(一)--- 基础知识 / 绘制线段圆弧 / 图片水印 / 截图
1.Quartz 2D是一个二维绘图引擎,同时支持ios和Mac系统: Quart2D的API是纯C语言的,API来自于Core Graphics框架: 2.Quartz 2D可以绘制图形(线段/三 ...
- 第1部分: 游戏引擎介绍, 渲染和构造3D世界
原文作者:Jake Simpson译者: 向海Email:GameWorldChina@myway.com ---------------------------------------------- ...
- iOS 开发:绘制像素到屏幕
转载:https://segmentfault.com/a/1190000000390012 译注:这篇文章虽然比较长,但是里面的内容还是很有价值的. 像素是如何绘制到屏幕上面的?把数据输出到屏幕的方 ...
- 小强学渲染之OpenGL渲染管线详析
什么是OpenGL? OpenGL是一套图形硬件的软件API接口库,它直接和GPU交互,将3D场景渲染绘制到2D屏幕上.总结说,OpenGL的功能是将程序中定义的各种2D或3D模型绘制到帧缓存中,或者 ...
随机推荐
- (转)elasticsearch5.2.2 压测配置
1.elasticsearch.yml # ---------------------------------- Cluster ----------------------------------- ...
- Mysql的表名/字段名/字段值是否区分大小写
1.MySQL默认情况下是否区分大小写,使用show Variables like '%table_names'查看lower_case_table_names的值,0代表区分,1代表不区分. 2.m ...
- oracle 数据库 命令
SQL PLUS 命令: SELECT * FROM ALL_TABLES;系统里有权限的表SELECT * FROM DBA_TABLES; 系统表SELECT * FROM USER_TABLES ...
- 第129天:node.js安装方法
node.js安装方法 第一步:双击node.js安装包开始安装,注意64位和32位,按照自己的进行安装 第二步:在安装过程中一直选择next,在选择安装目录时,大多数默认安装在C盘,我安装在了D盘, ...
- HUST1017-Exact Cover
给出一个\(n\times m\)的01矩阵,每行最多有\(c\)个1,求一个精确覆盖,即选出一些行使得每列有有且仅有一个1.输出方案. 分析 被这个题坑到了啊!!第一次上HUSTOJ做题,不知道没有 ...
- 转---秒杀多线程第十二篇 多线程同步内功心法——PV操作上 (续)
PV操作的核心就是 PV操作可以同时起到同步与互斥的作用. 1.同步就是通过P操作获取信号量,V操作释放信号量来进行. 2.互斥其实就是,同时操作P操作,结束后进行V操作即可做到. Java上实现PV ...
- ES2015中let的暂时性死区(TDZ)
Tomporal Dead Zone (TDZ)是ES2015中对作用域新的专用定义.是对于某些遇到在区块作用域绑定早于声明语句时的情况.Tomporal Dead Zone (TDZ)可以理解为时间 ...
- MySQL慢查询日志ES索引模板
{ "template": "mysql-slow-log-*", "settings": { "index": { & ...
- 洛谷 P1987 摇钱树
题目戳 题目描述 Cpg 正在游览一个梦中之城,在这个城市中有n棵摇钱树...这下,可让Cpg看傻了...可是Cpg只能在这个城市中呆K天,但是现在摇钱树已经成熟了,每天每棵都会掉下不同的金币(不属于 ...
- jQuery多重事件绑定
1. <a> a标签默认绑定了一个onclick事件,当自己再写一个onclick事件的时候,默认自己写的那个优先执行. 如下程序,先执行(123),然后再发生跳转. <!DOCTY ...