V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
GrapeCityChina
V2EX  ›  程序员

HTML 界的“苏炳添”——详解 Canvas 优越性能和实际应用

  •  
  •   GrapeCityChina ·
    GrapeCity · 2021-08-24 11:05:56 +08:00 · 980 次点击
    这是一个创建于 966 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Google Docs 宣布将会把 HTML 迁移到基于 Canvas 渲染,这一消息的出现再次把几年前随 HTML5 诞生的标签重新推到了人们视线之中。Canvas 在刚推出时主打的优势就是更快的渲染速度,堪称 HTML 届的“苏炳添”,刷新了人们对 Web 页面元素绘制速度的印象。但 Canvas 的优势仅限于此吗?

    (苏炳添,亚洲百米第一人)

    HTML 绘图届的前辈:SVG

    Canvas 是 HTML5 时代引入的“新”标签。与很多标签不同,Canvas 不具有自己的行为,只将一组 API 展现给客户端 JavaScript,让开发者使用脚本把想绘制的东西画到一张画布上。

    在 HTML5 之前,人们通常使用 SVG 来在页面上绘制出图形。SVG 使用 XML 来定义图形,就像使用 HTML 标签和样式定义 DIV 一样,我们也可以将一个空白的 DIV 想象为长方形的 SVG,两者的设计思想是相通的,SVG 的本质就是一个 DOM 元素。而 Canvas 则不同,Canvas 提供的是 JavaScript 的绘图 API,而不是像 SVG 那样使用 XML 描述绘图,通过 JavaScript API 直接完成绘制,比起修改 XML 来说要更简便、更直接。

    除了定义的方式不同,Canvas 和 DOM (当然也包含 SVG )的差异更多的体现在浏览器的渲染方式上。

    浏览器在做页面渲染时,Dom 元素是作为矢量图进行渲染的。每一个元素的边距都需要单独处理,浏览器需要将它们全都处理成像素才能输出到屏幕上,计算量十分庞大。当页面上内容非常多,存在大量 DOM 元素的时候,这些内容的渲染速度就会变得很慢。

    ( Canvas )

    而 Canvas 与 DOM 的区别则是 Canvas 的本质就是一张位图,类似 img 标签,或者一个 div 加了一张背景图( background-image )。所以,DOM 那种矢量图在渲染中存在的问题换到 Canvas 身上就完全不同了。在渲染 Canvas 时,浏览器只需要在 JavaScript 引擎中执行绘制逻辑,在内存中构建出画布,然后遍历整个画布里所有像素点的颜色,直接输出到屏幕就可以了。不管 Canvas 里面的元素有多少个,浏览器在渲染阶段也仅需要处理一张画布。

    然而这样更加强大的功能,不可避免的让使用 canvas 渲染有很高的门槛。Google Docs 在构建 Canvas 的过程中重新定义了往常已经被人们所熟悉的内容,例如精确定位、文本选择、拼写检查、重画调优等。为什么更多开发者还是选择了接纳 Canvas 这个门槛更高的技术路线呢?这就得回到 Canvas 的最大优势:渲染性能。

    Canvas 的渲染模式

    这里的渲染是指浏览器将页面的代码呈现为屏幕上内容的过程。Canvas 和 Dom 的渲染模式完全不同,搞清楚这个差异对理解 Canvas 的性能优势至关重要。

    Dom:驻留模式

    驻留模式( Retained Mode )是 Dom 在浏览器中的渲染模式。下图粗略展示了这一过程的工作流程。

    (驻留模式)

    DOM 的核心是标签,一种文本标记型语言,多样性很强且多个标签之间存在各种关联(如在同一个 DIV 下设置为 float 的子 DIV )。浏览器为了更好的处理这些 DOM 元素,减少对绘制 API 的调用,就设计了一套将中间结果存放于内存的“驻留模式”。首先,浏览器会将解析 DOM 相关的全部内容(包含 HTML 标签、样式和 JavaScript ),将其转化为场景( scene )和模型( model )存储到内存中,然后再调用系统的绘制 API (如 Windows 程序员熟悉的 GDI/GDI+),把这些中间产物绘制到屏幕。

    驻留模式通过场景和模型缓存减少了对绘制 API 的调用频次,将性能压力转移到场景和模型生成阶段,即浏览器需要根据 DOM 上下文和 BOM 中的尺寸数据,“自行判断”每一个元素的绘制结果。

    Canvas:快速模式

    Canvas 采用了和 DOM 不同的快速模式( Immediate Mode ),让我们先来看看快速模式是如工作的:

    (快速模式)

    Canvas 的应用优点

    上面介绍的两种不同的模式直接造成了 Dom 和 Canvas 的性能差异。对于使用快速模式渲染的 Canvas 而言,浏览器的每次重绘都是基于代码的,不存在能让处理流程变慢的多层解析,所以它真的很快。除了快之外,Canvas 的灵活性也大大超出 DOM 。我们可以通过代码精确的控制如何、何时绘制出我们想要的效果。

    在资源消耗上,DOM 的驻留模式意味着场景中每增加一点东西就需要额外消耗一些内存,而 Canvas 并没有这个问题。这个差异会随着页面元素的数量增多而愈加明显。以 B 端的企业应用场景为例,表单那种数据量比较小的场景,不同渲染模式带来的效果差异并不明显;但在工业制造、金融财会等类 Excel 电子表格操作的场景下,单元格数量动辄便是上百万( 5 万行 x 20 列)甚至上亿个,浏览器需要对表格所有单元格本身内容进行渲染,同时还涉及到丰富的数据处理,情况就完全不同了。

    ( Web 页面上的电子表格,包含 1 百万个单元格)

    在 Canvas 出现之前,在前端渲染表格时只能通过构建复杂的 DOM 来实现。这种方式下,浏览器的性能成为了 Web 应用瓶颈,让很多开发者放弃了在浏览器上实现电子表格的想法。

    在 Canvas 出现后,快速模式带来的性能优势无疑是一个巨大的亮点,大量、复杂的 DOM 渲染处理带来的性能问题终于有了解决途径。

    回到电子表格的应用场景,业内已经出现了使用 Canvas 绘制画布的表格组件,这类组件在渲染数据层时不仅无需重复创建和销毁 DOM 元素,在画布的绘制过程中,也比 Dom 元素渲染的限制更少。除了表格之外,Canvas 也为数字孪生可视化大屏、页面游戏等场景带来了变革。

    (数字孪生大屏,精确控制各种形状、样式)

    总结

    总结一下,在渲染模式上,Canvas 站在了 DOM 的对面,浏览器对其内容一无所知,一切渲染的权利回到了开发者的手上,这个改变带来了显著的性能优势。此外,我们可以使用 Canvas 绘制种类更为丰富的 UI 元素,如线形、特殊图形等,通过画法逻辑,还可以实现更加精准的 UI 界面渲染,解决了浏览器差异造成的样式误差,让更多应用场景可以顺利迁移到 Web 平台上来。

    参考资料:

    ·       Canvas 的 Wiki 介绍

    ·       Canvas 社区

    ·       基于 Canvas 表格组件 SpreadJS

    转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。

    AoEiuV020
        1
    AoEiuV020  
       2021-08-24 11:16:48 +08:00
    这都能蹭苏的热度简直了,
    ensonmj
        2
    ensonmj  
       2021-08-24 17:38:03 +08:00
    canvas 最大的问题就是没有事件回调吧?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5558 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 38ms · UTC 07:50 · PVG 15:50 · LAX 00:50 · JFK 03:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.