WebKit的一些笔记3(基础篇)

来源:互联网 发布:师洋淘宝店骂人 编辑:程序博客网 时间:2024/06/05 10:52

Webkit渲染基础

概述

Webkit是一个渲染引擎,而不是浏览器,它专注于网页内容的展示,其中渲染是其中的核心功能之一。
DOM称作文本对象模型,简单来说,是对HTML或者XML等文档的结构化表示方法,通过这种方式,用户可以通过接口访问HTML页面任何元素的相关属性,并可以对DOM进行相应的操作。
对于DOM树的可视节点,WebKit需要创建相应的RenderObject节点,这些节点构成了一颗Render树。基于Render树,WebKit根据某种规则会创建RenderLayer节点,构成一颗RenderLayer树。WebKit的布局计算,浏览器的渲染,GPU的硬件加速都依赖于Render树和RenderLayer树
DOM、Render树和RenderLayer树如下图所示:

Render树

Render树的建立

Render树节点和DOM树节点并不是一一对应的关系,如下情况需要建立Render节点:
  1. DOM树的document节点;
  2. DOM树中的可视化节点,例如HTML、BODY、DIV等;
  3. 某些情况下需要建立匿名的Render节点,该节点不对应DOM树上的任何节点

RenderObject类及其子类

RenderObject是Render树的节点基础类,提供了一组公共的接口。
RenderObject有很多子类,子类可能是DOM树中的节点,也可能是容器类,如RenderBlock,它是一个非常重要的类。
附上一张继承图:

匿名的RenderBlock对象

(这块不是很懂,先不写了)

RenderLayer树

RenderLayer树是基于Render树重新建立起来的一颗新的树。RenderLayer节点和Render节点是一对多的关系。
下面情况下,需要建立新的RenderLayer节点:
(这块也不是很了解,也先不写了)

渲染主循环(main loop)和requestAnimationFrame

背景

在JavaScript中有如下两个函数:
  • setTimeout:在指定毫秒数之后调用函数或者表达式,只调用一次,如果需要多次调用,则调用setInterval(),或者让代码本身调用setTimeout();
  • setInterval:按照指定的毫秒周期来调用某段代码。
我们可以通过以上两个函数让浏览器周期性的做一些事情,比如更新动画,但是会存在以下几个问题:
  1. 时间间隔不好控制,动画可能不平滑;
  2. 可能会受浏览器和平台不同等因素的影响;
  3. 回调函数的复杂性。
于是我们引入requestAnimationFrame方法,该方法告诉浏览器JavaScript想发起一个动画帧,然后在动画帧绘制前,需要做一些动作,这样浏览器可以根据需要来优化自己的mainloop机制和调用的时间点,已达到平衡的效果。

渲染mainloop

Browser进程UI的mainloop和Render进程的mainloop是两个进程,互不影响,但是问题依然存在。Render进程的渲染和JavaScript的执行都在其主线程中,由mainloop来调度。主线程采用一个大循环加上一个事件队列来处理这个竞争关系。

从上面可以看出:
  1. 如果队列中的事件过多,很多事件的来不及处理,会造成事件的平均等待时间会比较长;
  2. 如果事件的处理函数需要的时间很长,会造成后面的事件一直等待,也会造成延迟。

WebKit和Chromium中的实现

下面来看看setTimeout和setInterval的实现。

WebKit会为DOM中的每个setTimeout和setInterval的调用创建一个DOMTimer,而后对象会由ThreadTimers负责管理,内部实际上是一个最小堆,每次取timeout时间最小的,同时相同的Timer可以合并。
当Timer超时后,Chromium清除该Timer对象,同时调用它的回调函数,回调函数通常会更新页面的样式和布局,这会触发relayout,从而触发立即重新绘制一个新帧。
如上所述,这两个函数有如下不足:不考虑浏览器繁忙或者被隐藏,它们只要要求浏览器去做,造成了资源极大的浪费,而且浏览器帧间隔有可能比它们设置的间隔大,强制绘制的话,用户也是看不到的。
再来看看requestAnimationFrame的实现,其原理就是:申请绘制下一帧,至于什么时候绘制由浏览器来决定,浏览器会在绘制前调用回调函数。
基本过程(略)。
Chromium对requestAnimation有三大设计原则:
  1. 当页面不可见时,其回调函数不会被调用,减少CPU和GPU的消耗;
  2. 其调用频率不会超过60hz(显示器的刷新频率);
  3. 只有当页面真正开始渲染的时候,回调函数才会被调用。
编程时候的注意事项:
  1. 回调函数不能太大,不能太占用时间;
  2. requestAnimationFrame不需要设置时间间隔,由浏览器控制,不需要程序员担心;
  3. 回调函数无需合并。

0 0
原创粉丝点击