来自 前端知识 2019-11-08 09:11 的文章
当前位置: 金沙澳门官网网址 > 前端知识 > 正文

澳门金莎娱乐手机版:用CSS开启硬件增加速度来

记一次淘宝首页奇葩的渲染问题

2015/11/23 · CSS · 渲染

原文出处: 淘宝前端团队(FED)- 阎王   

澳门金莎娱乐手机版 1

或许你曾经在 Chrome 浏览器上碰到过这样让人瞠目结舌的问题:

  • hover 触发一个层展示,hover 离开后,这个层还遗留残影
  • 浏览器没有清理一个元素渲染的上一个状态,导致页面多出一个错位的跟该元素一模一样的影子
  • 交互时突然出现一个方形色块,覆盖在元素上
  • 或者还有更奇葩的……

以上列举到的三个问题,我在维护淘宝首页的时候都遇到过。这些都是浏览器渲染页面时,因为渲染引擎的 bug 导致的问题,不常见,更加难以写 demo 演示,它们只在特定的复杂场景下,程序计算存在误差或者漏洞的时候出现,尤其是涉及到边界判断的时候。

1. 何为硬件加速

问题复现

很难得有机会让我碰到一个可以复现的,我把它记录下来了。如下图所示,hover 到学习模块的边界位置时:

澳门金莎娱乐手机版 2

手动 hover 和模拟 hover 都有一样的问题,没有多想,立马加上了一句话修复了这个问题:

CSS

.channel2 .channel-item { transform: translateZ(0); }

1
2
3
.channel2 .channel-item {
    transform: translateZ(0);
}

这个不是直觉,多次遇到这种奇葩问题,我第一想到的便是使用 3D 加速将这个渲染层隔离渲染,80% 以上的概率能够解决问题,而解决问题的关键在于找准加这句代码的 DOM 元素。

就是将浏览器的渲染过程交给GPU处理,而不是使用自带的比较慢的渲染器。这样就可以使得animation与transition更加顺畅。

探索 bug

这个层在我的代码中肯定是不存在的,我们只能用 bug 来形容这个问题。因为元素刚好贴在 .channel2 的边界,猜测应该跟层渲染有关,于是打开了控制台 ESC -> Rendering -> Show layer borders,看到了这个:

澳门金莎娱乐手机版 3

仔细观察,可以看到,这个粉色块在瓦片边界和父元素边界之中,可以断定,这几个瓦片在渲染的时候存在问题。


这里需要补充下关于瓦片的知识。瓦片,英文里头称之为 tile,它是 webkit/blink 渲染页面时的中间过程,将整个页面分成多个大小一样的瓦片,并发渲染每个瓦片的内容。一个元素开启 3D 硬件加速之后,会变成一个独立的层,这个层的渲染也会被分割成瓦片,可以想象成一个子页面。

瓦片和瓦片之间的边界计算是处理的难点,因为渲染的内容不能错位。


其实让我找到问题根本原因的是,rendering 块的颜色,平时在网页上开启 show layer borders 看到的是半透明的绿色块,而这里显示的是粉色块,搜索了下不同色块代表的含义,没找到具体的文档说明,但是找到了 代码:

JavaScript

// Missing resize invalidations are in salmon pink. SkColor DebugColors::MissingResizeInvalidations() { return SkColorSetARGB(255, 255, 155, 170); }

1
2
3
4
// Missing resize invalidations are in salmon pink.
SkColor DebugColors::MissingResizeInvalidations() {
  return SkColorSetARGB(255, 255, 155, 170);
}

对应的就是这个颜色,“缺失调整验证”,在 chromium 的源码仓库中搜了上面的代码,找到了 具体说明:

JavaScript

if (!deflated_content_rect.Contains(canvas_playback_rect)) { if (clear_canvas_with_debug_color) { // Any non-painted areas outside of the content bounds are left in // this color. If this is seen then it means that cc neglected to // rerasterize a tile that used to intersect with the content rect // after the content bounds grew. canvas->save(); canvas->translate(-canvas_bitmap_rect.x(), -canvas_bitmap_澳门金莎娱乐手机版 ,rect.y()); canvas->clipRect(gfx::RectToSkRect(content_rect), SkRegion::kDifference_Op); canvas->drawColor(DebugColors::MissingResizeInvalidations(), SkXfermode::kSrc_Mode); canvas->restore(); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if (!deflated_content_rect.Contains(canvas_playback_rect)) {
  if (clear_canvas_with_debug_color) {
    // Any non-painted areas outside of the content bounds are left in
    // this color.  If this is seen then it means that cc neglected to
    // rerasterize a tile that used to intersect with the content rect
    // after the content bounds grew.
    canvas->save();
    canvas->translate(-canvas_bitmap_rect.x(), -canvas_bitmap_rect.y());
    canvas->clipRect(gfx::RectToSkRect(content_rect),
                     SkRegion::kDifference_Op);
    canvas->drawColor(DebugColors::MissingResizeInvalidations(),
                      SkXfermode::kSrc_Mode);
    canvas->restore();
  }
}

这里能看的肯定就是注释啦,没有太多上下文,看的挺头痛!大致翻译了下上下几段注释:

  1. 即使完全覆盖,对于触碰到渲染层边界的栅格化处理,我们依然需要,在上次记录没有覆盖到的纹理下方和纹理化线性过滤的上方,栅格化处理背景颜色。
  2. 内容的最后的纹理可能只有部分被栅格覆盖
  3. 在内容边界外没有被渲染到的部分将使用 MissingResizeInvalidations 颜色,如果这个块能够被看见,那就意味着程序忽视处理了内边边界增长之后栅格化与内容相交的瓦片。

从第三句大致可以了解到,因为元素的边界增长导致了这个渲染 bug,回头看了下元素的边界状态,果然…

我们可以在浏览器中用css开启硬件加速,使GPU (Graphics Processing Unit) 发挥功能,从而提升性能

直接原因

我们看看 hover 上去之后,层边界的变化:

澳门金莎娱乐手机版 4

很明显,这里的高度溢出了,但是没有处理,看了下这个元素的 css,确实高度上没有做处理,在元素上添加

CSS

.channel-item { overflow: hidden; }

1
2
3
.channel-item {
  overflow: hidden;
}

同样可以解决问题。

最后的解决手段:

澳门金莎娱乐手机版 5

层渲染的问题我还是比较喜欢使用 3d 硬件加速来处理,而 overflow:hidden 这样的 css 布局处理上,我是不太推荐的,搞不好就把哪个重要的内容隐藏掉了。

现在大多数电脑的显卡都支持硬件加速。鉴于此,我们可以发挥GPU的力量,从而使我们的网站或应用表现的更为流畅。

类似问题处理方案

如果以后大家遇到类似的问题,可以打开 chrome 的层和瓦片分析工具,看看渲染出来的块有没有异常色块,尤其是粉色块。也可以观察交互过程中,元素的边界有没有变化。

CSS 在浏览器中的渲染是我们触及比较少的知识,如果想迅速找到问题,必须对浏览器的渲染原理有所了解,并且能够熟练的使用 chrome 提供的调试工具,这是基础。

1 赞 1 收藏 评论

澳门金莎娱乐手机版 6

2硬件加速原理

浏览器接收到页面文档后,会将文档中的标记语言解析为DOM树。DOM树和CSS结合后形成浏览器构建页面的渲染树。渲染树中包含了大量的渲染元素,每一个渲染元素会被分到一个图层中,每个图层又会被加载到GPU形成渲染纹理,而图层在GPU中transform 是不会触发 repaint 的,最终这些使用 transform 的图层都会由独立的合成器进程进行处理。

CSS transform 会创建了一个新的复合图层,可以被GPU直接用来执行 transform 操作。

浏览器什么时候会创建一个独立的复合图层呢?事实上一般是在以下几种情况下:

  • 3D 或者 CSS transform
  • <video> 和 <canvas> 标签
  • CSS filters
  • 元素覆盖时,比如使用了 z-index 属性

 

3 为什么硬件加速会使页面流畅

因为 transform 属性不会触发浏览器的 repaint(重绘),而绝对定位absolute中的 left 和 top 则会一直触发 repaint(重绘)。

为什么 transform 没有触发 repaint 呢?简而言之,transform 动画由GPU控制,支持硬件加速,并不需要软件方面的渲染。

 

浏览器什么时候会创建一个独立的复合图层呢?事实上一般是在以下几种情况下:

3D 或者 CSS transform

<video> 和 <canvas> 标签

CSS filters

元素覆盖时,比如使用了 z-index 属性

 

4并不是所有的CSS属性都能触发GPU的硬件加速,实际上只有少数属性可以,比如下面的这些:

transform

opacity

filter

 

 

5.如何在桌面端和移动端用CSS开启硬件加速

CSS animations, transforms 以及 transitions 不会自动开启GPU加速,而是由浏览器的缓慢的软件渲染引擎来执行。那我们怎样才可以切换到GPU模式呢,很多浏览器提供了某些触发的CSS规则。

现在,像Chrome, FireFox, Safari, IE9+和最新版本的Opera都支持硬件加速,当它们检测到页面中某个DOM元素应用了某些CSS规则时就会开启,最显著的特征的元素的3D变换。

例如:

.cube {

   -webkit-transform: translate3d(250px,250px,250px)

   rotate3d(250px,250px,250px,-120deg)

   scale3d(0.5, 0.5, 0.5);

}

可是在一些情况下,我们并不需要对元素应用3D变换的效果,那怎么办呢?这时候我们可以使用个小技巧“欺骗”浏览器来开启硬件加速。

虽然我们可能不想对元素应用3D变换,可我们一样可以开启3D引擎。例如我们可以用transform: translateZ(0); 来开启硬件加速 。

.cube {

本文由金沙澳门官网网址发布于前端知识,转载请注明出处:澳门金莎娱乐手机版:用CSS开启硬件增加速度来

关键词: