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

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

HTML界的“苏炳添”——详解Canvas优越性能和实际应用的更多相关文章

  1. Android之canvas详解

    首先说一下canvas类: Class Overview The Canvas class holds the "draw" calls. To draw something, y ...

  2. 【转】Android Canvas绘图详解(图文)

    转自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1212/703.html Android Canvas绘图详解(图文) 泡 ...

  3. canvas arcTo()用法详解 – CodePlayer

    canvas arcTo()用法详解 – CodePlayer canvas arcTo()用法详解

  4. Canvas使用渐变之-径向渐变详解

    创建径向渐变使用 createRadialGrdient(x0,y0,r0,x1,y1,r1)​ 一共​六个参数,分别代表: 起点的圆心坐标(第一个和第二个参数), 起点园的半径(第三个参数), 终点 ...

  5. Android中Canvas绘图基础详解(附源码下载) (转)

    Android中Canvas绘图基础详解(附源码下载) 原文链接  http://blog.csdn.net/iispring/article/details/49770651   AndroidCa ...

  6. [js高手之路] html5 canvas系列教程 - 状态详解(save与restore)

    本文内容与路径([js高手之路] html5 canvas系列教程 - 开始路径beginPath与关闭路径closePath详解)是canvas中比较重要的概念.掌握理解他们是做出复杂canvas动 ...

  7. Android为TV端助力 转载:Android绘图Canvas十八般武器之Shader详解及实战篇(上)

    前言 Android中绘图离不开的就是Canvas了,Canvas是一个庞大的知识体系,有Java层的,也有jni层深入到Framework.Canvas有许多的知识内容,构建了一个武器库一般,所谓十 ...

  8. Android为TV端助力 转载:Android绘图Canvas十八般武器之Shader详解及实战篇(下)

    LinearGradient 线性渐变渲染器 LinearGradient中文翻译过来就是线性渐变的意思.线性渐变通俗来讲就是给起点设置一个颜色值如#faf84d,终点设置一个颜色值如#CC423C, ...

  9. 【微信小程序项目实践总结】30分钟从陌生到熟悉 web app 、native app、hybrid app比较 30分钟ES6从陌生到熟悉 【原创】浅谈内存泄露 HTML5 五子棋 - JS/Canvas 游戏 meta 详解,html5 meta 标签日常设置 C#中回滚TransactionScope的使用方法和原理

    [微信小程序项目实践总结]30分钟从陌生到熟悉 前言 我们之前对小程序做了基本学习: 1. 微信小程序开发07-列表页面怎么做 2. 微信小程序开发06-一个业务页面的完成 3. 微信小程序开发05- ...

随机推荐

  1. Bootstrap-table 显示行号

    趁热打铁,使用bootstrap-table时,想要显示每行的行号,再网上查了查,网上给的显示行号的大部分方法,只要一翻页,行号就会又从1开始计算, 也许没有碰到想要的,自己试着解决了这个问题,本人初 ...

  2. C语言代码段

    /* 功 能:将str字符串中的oldstr字符串替换为newstr字符串 * 参 数:str:操作目标 oldstr:被替换者 newstr:替换者 * 返回值:返回替换之后的字符串 */ char ...

  3. Ionic命令笔记

    Ionic命令:ionic serve 开启服务调试ionic cordova prepare android 生成android原生项目 ionic cordova run browser 打包成混 ...

  4. 聊聊 Spring AOP 的不为常知的“秘事”

    Spring AOP 在我们日常开发中扮演了一个非常重要的角色,对于如何使用 AOP 相信很多人已经不陌生,但其中有一些点却容易被我们忽视,本节我们结合一些"不为常知"的问题展开讨 ...

  5. ES6 对象定义简写及常用的扩展方法

    1.ES6 对象定义简写 es6提供了对象定义里的属性,方法简写方式: 假如属性和变量名一样,可以省略,包括定义对象方法function也可以省略 <script type="text ...

  6. .net core番外第2篇:Autofac的3种依赖注入方式(构造函数注入、属性注入和方法注入),以及在过滤器里面实现依赖注入

    本篇文章接前一篇,建议可以先看前篇文章,再看本文,会有更好的效果. 前一篇跳转链接:https://www.cnblogs.com/weskynet/p/15046999.html 正文: Autof ...

  7. P1447能量采集

    P1447能量采集 定义:(i,j)表示处于(i,j)的植物的贡献 我们发现,点(i,j)与(0,0)的连线所过整点的数目为\(\gcd(i,j)\) 发现要是想记录每个点的答案并不好算.那么怎么好算 ...

  8. 用好Git stash,助你事半功倍

    git stash: 用法:git stash list [<选项>] 或:git stash show [<选项>] [<stash>] 或:git stash ...

  9. 深入刨析tomcat 之---第13篇 tomcat的三种部署方法

    writedby 张艳涛 一般我们都知道将web 应用打成war包,放到tomcat的webapp目录下,就是部署了,这是部署方法1 第2种部署方法我们也知道,就是讲web应用的文件夹拷贝到webap ...

  10. HCNA Routing&Switching之交换技术基础

    什么是交换机?顾名思义,交换机就是用来数据包交换的:广泛用于终端接入:它的前身是hub(集线器),hub是一个古老的设备,它的作用也是用于终端接入,但hub有一个最大的缺点是它不能隔离冲突域:所谓冲突 ...