本文翻译自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)的更多相关文章

  1. ‎Cocos2d-x 学习笔记(25) 渲染 绘制 Render

    [Cocos2d-x]学习笔记目录 本文链接:https://www.cnblogs.com/deepcho/p/cocos2dx-render.html 1. 从程序入口到渲染方法 一个Cocos2 ...

  2. CSS性能优化的8个技巧

    本文作者:高峰,360奇舞团前端工程师,W3C性能工作组成员,同时参与WOT工作组的学习. 我们都知道对于网站来说,性能至关重要,CSS作为页面渲染和内容展现的重要环节,影响着用户对整个网站的第一体验 ...

  3. QML的渲染方式相较于之前的版本也有了重大的更新(CPU线程负责绘制,GPU线程负责渲染),还有好多经常评论 good

    作者:qyvlik链接:http://www.zhihu.com/question/38867614/answer/78583440来源:知乎著作权归作者所有,转载请联系作者获得授权. 做UI啊.如果 ...

  4. 渲染、render与绘制

    渲染是抽象到具体的过程: 抽象:图片信息的描述(比如一条线:两个端点的位置.线粗.颜色等特征): 具体:依据抽象信息得到的可视图片(绘制过程). 渲染是中文翻译的问题,有种添油加醋的感觉.直意就是交与 ...

  5. 源码分析篇 - Android绘制流程(二)measure、layout、draw流程

    performTraversals方法会经过measure.layout和draw三个流程才能将一帧View需要显示的内容绘制到屏幕上,用最简化的方式看ViewRootImpl.performTrav ...

  6. Quartz2D复习(一)--- 基础知识 / 绘制线段圆弧 / 图片水印 / 截图

    1.Quartz 2D是一个二维绘图引擎,同时支持ios和Mac系统: Quart2D的API是纯C语言的,API来自于Core  Graphics框架: 2.Quartz 2D可以绘制图形(线段/三 ...

  7. 第1部分: 游戏引擎介绍, 渲染和构造3D世界

    原文作者:Jake Simpson译者: 向海Email:GameWorldChina@myway.com ---------------------------------------------- ...

  8. iOS 开发:绘制像素到屏幕

    转载:https://segmentfault.com/a/1190000000390012 译注:这篇文章虽然比较长,但是里面的内容还是很有价值的. 像素是如何绘制到屏幕上面的?把数据输出到屏幕的方 ...

  9. 小强学渲染之OpenGL渲染管线详析

    什么是OpenGL? OpenGL是一套图形硬件的软件API接口库,它直接和GPU交互,将3D场景渲染绘制到2D屏幕上.总结说,OpenGL的功能是将程序中定义的各种2D或3D模型绘制到帧缓存中,或者 ...

随机推荐

  1. Ubuntu 下升级 php

    起因: 在现有的 Apache + PHP 环境下,增加一个 PHP Extension 扩展时,遇到错误: Unable to initialize moduleModule compiled wi ...

  2. default.properties文件

    在地址栏访问某个 action 之所以能访问到,只因为在 default.properties 配置文件中有一个键值对,key 为struts.action.extension,值为 action,, ...

  3. Graph-Based image segmentation method

    1.Graph-Based 方法简介 基于图的图像分割方法将图像伪造成带权值无向图的形式 : G = (V, E) 其中,V是顶点集合,把图像中的每个像素或者每个区域看成图的一个顶点:E是边的集合,连 ...

  4. floyd最短路

    floyd可以在O(n^3)的时间复杂度,O(n^2)的空间复杂度下求解正权图中任意两点间的最短路长度. 本质是动态规划. 定义f[k][i][j]表示从i出发,途中只允许经过编号小于等于k的点时的最 ...

  5. [十四]SpringBoot 之 Spring拦截器(HandlerInterceptor)

    过滤器属于Servlet范畴的API,与spring 没什么关系. Web开发中,我们除了使用 Filter 来过滤请web求外,还可以使用Spring提供的HandlerInterceptor(拦截 ...

  6. BZOJ3574 HNOI2014抄卡组(哈希)

    容易发现通配符中间的部分可以任意匹配,会造成的无法匹配的仅仅是前后缀,前缀和后缀可以分别独立处理.如果字符串均有通配符,只需要按前/后缀长度排序然后暴力匹配就可以了. 问题在于存在无通配符的字符串.显 ...

  7. Openssl的编译安装以及Vs2012上环境搭建教程

    Openssl的编译安装以及Vs2012上环境搭建教程 一.Openssl的编译安装 一.准备工作 1.Openssl下载地址:https://www.openssl.org/source/ 2.Ac ...

  8. Codeforces 744C. Hongcow Buys a Deck of Cards(状压DP)

    这题的难点在于状态的设计 首先显然是个状压,需要一维表示卡的状态,另一维如果设计成天数,难以知道当前的钱数,没法确定是否能够购买新的卡,如果设计成钱数,会发现状态数过多,空间与时间都无法承受.但是可以 ...

  9. bzoj3709: [PA2014]Bohater(贪心)

    贪心... 可以回血的按d[i]升序防止死掉 不能回血的按a[i]降序,因为只考虑d我们要扣除的血量是一定的,为了不死显然回血多的放前面更好 #include<iostream> #inc ...

  10. 【bzoj4872】【shoi2017】分手即是祝愿

    4872: [Shoi2017]分手是祝愿 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 746  Solved: 513[Submit][Statu ...