记一次淘宝首页奇葩的渲染问题
2015-12-23 13:23
288 查看
记一次淘宝首页奇葩的渲染问题
作者: 小胡子哥 2015-10-14 12:27:18 分类: 前端杂烩 标签: bug, 渲染 评论数: 9条评论或许你曾经在 chrome 浏览器上碰到过这样让人瞠目结舌的问题:
Hover触发一个层展示, hover离开后, 这个层还遗留残影
浏览器没有清理一个元素渲染的上一个状态, 导致页面多出一个错位的跟该元素一模一样的影子
交互时突然出现一个方形色块, 覆盖在元素上
或者还有更奇葩的…
以上列举到的三个问题, 我在维护淘宝首页的时候都遇到过。这些都是浏览器渲染页面时, 因为渲染引擎的 bug 导致的问题, 不常见, 更加难以写 demo 演示, 它们只在特定的复杂场景下, 程序计算存在误差或者漏洞的时候出现, 尤其是涉及到边界判断的时候。
问题复现
很难得有机会让我碰到一个可以复现的, 我把它记录下来了。如下图所示, hover 到学习模块的边界位置时:手动 hover 和模拟 hover 都有一样的问题, 没有多想, 立马加上了一句话修复了这个问题:
.channel2 .channel-item { transform: translateZ(0); } |
探索 bug
这个层在我的代码中肯定是不存在的, 我们只能用 bug 来形容这个问题。因为元素刚好贴在 .channel2的边界, 猜测应该跟层渲染有关, 于是打开了控制台
ESC -> Rendering -> Show layer borders, 看到了这个:
仔细观察, 可以看到, 这个粉色块在瓦片边界和父元素边界之中, 可以断定, 这几个瓦片在渲染的时候存在问题。
这里需要补充下关于瓦片的知识。瓦片, 英文里头称之为 tile, 它是 webkit/blink 渲染页面时的中间过程, 将整个页面分成多个大小一样的瓦片, 并发渲染每个瓦片的内容。一个元素开启 3D 硬件加速之后, 会变成一个独立的层, 这个层的渲染也会被分割成瓦片, 可以想象成一个子页面。
瓦片和瓦片之间的边界计算是处理的难点, 因为渲染的内容不能错位。
其实让我找到问题根本原因的是, rendering 块的颜色, 平时在网页上开启
show layer borders看到的是半透明的绿色块, 而这里显示的是粉色块,
搜索了下不同色块代表的含义, 没找到具体的文档说明, 但是找到了 代码:
// Missing resize invalidations are in salmon pink. SkColor DebugColors::MissingResizeInvalidations() { return SkColorSetARGB(255, 255, 155, 170); } |
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(); } } |
即使完全覆盖, 对于触碰到渲染层边界的栅格化处理, 我们依然需要,在上次记录没有覆盖到的纹理下方和纹理化线性过滤的上方,栅格化处理背景颜色。
内容的最后的纹理可能只有部分被栅格覆盖
在内容边界外没有被渲染到的部分将使用 MissingResizeInvalidations 颜色, 如果这个块能够被看见, 那就意味着程序忽视处理了内边边界增长之后栅格化与内容相交的瓦片。
从第三句大致可以了解到, 因为元素的边界增长导致了这个渲染 bug, 回头看了下元素的边界状态, 果然…
直接原因
我们看看 hover 上去之后, 层边界的变化:很明显, 这里的高度溢出了, 但是没有处理, 看了下这个元素的 css, 确实高度上没有做处理, 在元素上添加
.channel-item { overflow: hidden; } |
最后的解决手段:
层渲染的问题我还是比较喜欢使用 3d 硬件加速来处理, 而
overflow:hidden这样的 css 布局处理上, 我是不太推荐的, 搞不好就把哪个重要的内容隐藏掉了。
类似问题处理方案
如果以后大家遇到类似的问题, 可以打开 chrome 的层和瓦片分析工具, 看看渲染出来的块有没有异常色块, 尤其是粉色块。也可以观察交互过程中, 元素的边界有没有变化。CSS 在浏览器中的渲染是我们触及比较少的知识, 如果想迅速找到问题, 必须对浏览器的渲染原理有所了解, 并且能够熟练的使用 chrome 提供的调试工具, 这是基础。
本文链接:http://www.barretlee.com/blog/2015/10/14/a-incredible-bug-in-taobao
相关文章推荐
- Intellij Idea15 快捷键设置大全
- 杭电OJ2680(dijkstra)choose the best route
- mysql 修改root密码
- 破坏性创新第一原则
- Java泛型
- VB操作EXCEL文件大全
- hdu1150——最小点覆盖
- Xcode7.2注释插件失效
- mybatis 缓存
- http://blog.csdn.net/tangaowen/article/details/8551762
- fieldset和legend
- 安全监控、告警及自动化!
- 微信JS-SDK 修改分享标题 分享图片
- unity3D让物体惯性的旋转
- sql server 的cpu使用率过高的分析
- 函数preg_replace()与str_replace()
- 在使用Cocos2d-JS 开发过程中需要用到的单体设计模式
- kvm快照
- Centos中彻底删除Mysql(rpm、yum安装的情况)
- MySQL数据库操作常用脚本