一、什么是Canvas

想必学习前端的同学们对Canvas 都不陌生,它是 HTML5 新增的“画布”元素,可以使用JavaScript来绘制图形。

Canvas元素是在HTML5中新增的标签用于在网页实时生成图像,并且可以操作图像内容,基本上它是一个可以用JavaScript操作的位图(bitmap)。Canvas 由一个可绘制区域HTML代码中的属性定义决定高度和宽度。JavaScript代码可以访问该区域,通过一套完整的绘图功能的API生成动态的图形。

二. 引入Canvas的重要性

HTML5 在 2012 年已形成了稳定的版本,在此之前很长一段时间,开发者们绘制图形选择的方案更多是SVG来实现。SVG使用XML来定义图形,就像使用HTML标签一样来控制元素的排布,SVG的本质就是一个DOM元素。当图形内容太过丰富后,性能和内存上就会大打折扣。一旦涉及频繁的图片绘制场景,这个实现对于用户的体验将是毁灭性的。

渲染动画的基本原理,无非是反复地擦除和重绘。为了动画的流畅,留给开发者渲染一帧的时间,只有短短的 16.67ms。在这16.67ms中,我不仅需要处理一些绘制逻辑,计算每个对象的位置、状态,还需要把它们都画出来。如果消耗的时间稍稍多了一些,用户就会感受到“卡顿”。所以,在编写动画时,开发者们无时无刻不担忧着动画的性能,唯恐渲染的耗时过长。

在现代 Web 开发中,开发者们更多的会借助 Canvas 提供的API去绘制上下文,可以自由绘制各种2D和3D图形,创建富有视觉冲击力的游戏场景和角色。Canvas的使用可以使得游戏能够实现流畅的动态效果和用户交互。无论是简单的小游戏还是复杂的游戏引擎,Canvas 都被广泛应用。

下面是做的一个简单的对比试验,可以很明显感受到两者的差距,分别使用SVG和Canvas绘制一个包含着100w个圆形的500*500的图片,根据耗时计算对比,Canvas耗费的时间几乎只有SVG的一半:

三. 计算与渲染

把动画的一帧渲染出来,需要经过以下步骤:

  1. 计算:处理网页渲染逻辑,计算每个对象的状态和位置。
  2. 渲染:真正把对象绘制出来。
  3. JavaScript 调用 DOM API(包括 Canvas API)以进行渲染。
  4. 浏览器(通常是另一个渲染线程)把渲染后的结果呈现在屏幕上的过程。

之前提到过,在动画设计和开发中,每帧只有16.67毫秒的时间用于渲染。这个数值是通过计算每秒60帧得出的平均每帧渲染时间。实际上,并不是所有设备都能够稳定地达到60FPS。因此,为了确保在不同设备上实现一致性的动画效果,最好将每帧的渲染时间控制在10毫秒以内。

大家都知道,通常情况下,渲染的开销远大于计算(相差3~4个量级)。除非使用了一些时间复杂度很高的算法,否则不需要过于深入优化计算环节。Canvas的渲染是在JavaScript引擎中执行绘制逻辑,通过构建画布在内存中,并遍历所有像素点的颜色,最终输出到屏幕上。这种强大的功能可能会增加学习成本,但如今仍然有很多开发者选择和接受Canvas,这要归功于Canvas最大的优势:渲染性能的出色表现。

四. Canvas渲染性能优势

当谈论图形渲染技术时,就不得不提到DOM驻留模式和Canvas快速模式。

DOM驻留模式

DOM驻留模式是一种基于文档对象模型(DOM)的渲染技术。在DOM驻留模式下,页面的布局和样式是由DOM树来掌管的。当页面需要更新时,浏览器会重新计算布局和样式并重新渲染。此模式非常灵活,特别适用于处理动态页面交互和多样化的样式控制。然而,由于需要频繁地重新计算布局和样式,对于复杂的图形渲染任务来说,性能开销相对较高。

Canvas快速模式

Canvas快速模式利用HTML5的Canvas元素进行图形渲染。在这种模式下,开发者可以使用Canvas提供的2D或3D绘图API直接在画布上绘制图形。相比于DOM驻留模式,Canvas快速模式更加高效。它不关心页面的布局和样式,而是在需要时只重绘受影响的部分。这样就避免了频繁的布局和样式计算,提高了渲染性能。

  1. 分层提高Canvas性能

开发者们通过分析大量实际场景,总结出一套可以进一步提升Canvas性能的策略,即对变化较少和变化较多的内容进行分开渲染。这种策略就是所谓的分层Canvas。它能够显著降低完全没有必要的渲染性能开销。分层渲染的思想被广泛应用于各种图形相关的领域,从古老的皮影戏、套色印刷术,到现代电影/游戏工业以及虚拟现实领域等等。而分层Canvas只是分层渲染思想在Canvas动画上的一个基础应用。

分层Canvas的核心理念是,动态页面中的每种元素(层)对于渲染频率的需求是不同的。对于许多金融会计等大数据行业的从业者来说,主要数据内容的变化频率和幅度较大(他们通常面临数据变动和频繁计算),而背景表格样式的变化频率或幅度相对较小(基本不变,或者变化缓慢,或者仅在特定时机变化)。因此,需要频繁更新和重绘数据,但对于背景,可能只需要绘制一次,或者每隔200毫秒才重绘一次,而没有必要每16毫秒就重绘一次。

  1. 视野之外的绘制

在许多情况下,Canvas 仅仅作为数据展示页面的一部分,充当着一个“窗口”的角色。如果在每次数据更新时,都将所有数据完全绘制到 Canvas 上,很可能会出现大量内容绘制到Canvas 范围之外的情况。虽然调用了绘制 API,但实际上并没有产生任何效果。

因此,判断对象是否位于 Canvas 范围内需要进行额外的计算(例如,需要通过对游戏角色的全局模型矩阵求逆来得出对象的世界坐标,这是一项相对耗时的操作),同时也会增加代码的复杂性。因此,关键是是否需要这样做。

通过在本地代码中进行测试,比较了在视野内和视野外分别绘制100万个圆的耗时。在视野内绘制耗时8936ms,而在视野外绘制耗时2540ms。考虑到计算和绘制之间的耗时差距在3~4个数量级,因此通过计算来判断并避免绘制视野外的内容是一种非常有效的方法。

五. Canvas的应用

之前探讨了SVG和Canvas的绘制性能差异以及Canvas常见的优化方法。知道,对于使用快速模式渲染的Canvas来说,浏览器的每次重绘都是由代码驱动的,无须进行多层解析,因此它的速度非常快。除了速度快之外,Canvas的灵活性也显著优于DOM。可以通过代码精确控制何时以及如何绘制出期望的效果。

在资源消耗方面,DOM的驻留模式意味着场景中的每一个新增元素都会导致额外的内存消耗,而Canvas则没有这个问题。这种差异在页面元素数量增多时尤为明显。

在Canvas出现之前,前端渲染表格只能通过构建复杂的DOM来实现。然而,这种方式会导致浏览器性能成为Web应用的瓶颈,许多开发人员因此放弃了在浏览器上实现电子表格的想法。

Canvas出现后,其快速模式带来的出色性能优势成为了一大亮点,大量、复杂的DOM渲染处理所带来的性能问题因此有了解决之道。

回到电子表格的应用场景,现在已经出现了使用Canvas绘制画布的表格组件。这类组件在渲染数据层时无须重复创建和销毁DOM元素,而且在画布的绘制过程中受到的限制也比DOM元素渲染更少。其中,葡萄城公司的纯前端表格控件——SpreadJS就用到了Canvas实现表格绘制,除了表格之外,Canvas也为数字孪生可视化大屏、页面游戏等应用场景带来了变革(如下图所示)。

六、总结

本文通过介绍Canvas的原理、Canvas的重要性、Canvas在计算与渲染上的作用、Canvas渲染性能优势和Canvas的应用这五个部分,全面而系统地阐述了HTML Canvas在高性能渲染方面的相关知识和技巧。希望读者通过阅读本文能够深入了解Canvas的基本原理和特性,认识到Canvas在Web开发中的重要性,并掌握Canvas在计算与渲染上的作用。

七. 参考文章

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

《什么是canvas?有什么用?》黑马程序员

《Canvas最佳实践(性能篇)》

扩展链接:

如何在前端系统中使用甘特图

窗口函数大揭秘!轻松计算数据累计占比,玩转数据分析的绝佳利器

探秘移动端BI:发展历程与应用前景解析

Redis从入门到实践

一节课带你搞懂数据库事务!

Chrome开发者工具使用教程

解析Html Canvas的卓越性能与高效渲染策略的更多相关文章

  1. Gson全解析(下)-Gson性能分析

    前言 在之前的学习中,我们在Gson全解析(上)Gson使用的基础到分别运用了JsonSerializer和JsonDeserializer进行JSON和java实体类之间的相互转化. 在Gson全解 ...

  2. [No0000143]Win10“卓越性能模式”

    从不久之前Win10更新1803以来,微软不仅带来了一些新功能(和BUG),还悄悄地加入了一个“卓越性能模式”,老张想了想,不对呀,以前就有了一个“高性能模式”,这怎么就还多出个新的性能模式来,难道会 ...

  3. Kafka设计解析(五)Kafka性能测试方法及Benchmark报告

    转载自 技术世界,原文链接 Kafka设计解析(五)- Kafka性能测试方法及Benchmark报告 摘要 本文主要介绍了如何利用Kafka自带的性能测试脚本及Kafka Manager测试Kafk ...

  4. windows10 卓越性能模式

    打开cmd,输入 powercfg -duplicatescheme e9a42b02-d5df-448d-aa00-03f14749eb61 再到电池选项里,勾选卓越性能模式 若没出现卓越性能,创建 ...

  5. 美团开源Graver框架:用“雕刻”诠释iOS端UI界面的高效渲染

    Graver 是一款高效的 UI 渲染框架,它以更低的资源消耗来构建十分流畅的 UI 界面.Graver 独创性的采用了基于绘制的视觉元素分解方式来构建界面,得益于此,该框架能让 UI 渲染过程变得更 ...

  6. web性能优化-浏览器渲染原理

    在web性能优化-浏览器工作原理中讲到,浏览器渲染是在renderer process中完成的. 那我们来看下renderer process究竟干了什么? Renderer Process包含的线程 ...

  7. 在线抠图网站速抠图sukoutu.com全面技术解析之canvas应用

    技术关键词 Canvas应用,泛洪算法(Flood Fill),图片缩放,相对位置等比缩放,判断一个点是否在一个平面闭合多边形,nginx代理 业务关键词 在线抠图,智能抠图,一键抠图,钢笔抠图,矩阵 ...

  8. java中常见的json解析方法、库以及性能对比

    常见的json解析有原生的JSONObject和JSONArray方法,谷歌的GSON库,阿里的fastjson,还有jackson,json-lib. Gson(项目地址:https://githu ...

  9. OpenHarmony 3.1 Beta 版本关键特性解析——ArkUI canvas组件

    (以下内容来自开发者分享,不代表 OpenHarmony 项目群工作委员会观点) 江英杰 华为技术有限公司 canvas 是 ArkUI 开发框架里的画布组件,常用于自定义绘制图形.因为其轻量.灵活. ...

  10. Kafka设计解析(五)- Kafka性能测试方法及Benchmark报告

    本文转发自Jason’s Blog,原文链接 http://www.jasongj.com/2015/12/31/KafkaColumn5_kafka_benchmark 摘要 本文主要介绍了如何利用 ...

随机推荐

  1. 重磅发布:微服务引擎 MSE 专业版

    简介: 性能提升 10 倍,更高的 SLA 保障,新用户限时抢购 8 折资源包. 微服务引擎 MSE 专业版发布,支持 Nacos 2.0 ,相比基础版,专业版具有更高的 SLA 保障,性能提升十倍, ...

  2. [FAQ] 钉钉 Excel 回车键不能换行 ? 在线编辑如何换行

      Win 端表格换行:AIT+ENTER Mac 端表格换行:AIT OPTION+ENTER Tool:ChatAI Refer:钉钉技巧 Refer:https://www.dingtalk.c ...

  3. 使用Kafka Assistant监控Kafka关键指标

    使用Kafka Assistant监控Kafka关键指标 使用Kafka时,我们比较关心下面这些常见指标. Kafka Assistant下载地址:http://www.redisant.cn/ka ...

  4. spannerlib优雅的go异常处理

    蹩脚的go 异常处理 一般写go的人,如果他不是写算法,正常写业务代码的话,可能都会为优雅的异常处理而烦恼,因为脑子抽筋的go设计者们,总是感觉语法糖是一种很低级的东西.但是在我们大多数公司的业务逻辑 ...

  5. 自动化测试数据生成:Asp.Net Core单元测试利器AutoFixture详解

    引言 在我们之前的文章中介绍过使用Bogus生成模拟测试数据,今天来讲解一下功能更加强大自动生成测试数据的工具的库"AutoFixture". 什么是AutoFixture? Au ...

  6. 中国ITSM研发创新之路

    沿着 itil v3+java流程引擎 的老套路没办法搞出新的名堂了,所以必须要创新1. 理论创新关于ITIL辩证分析的文章我已经写了很多,不一一赘述.我的观念是与其坐等洋和尚来洗脑宣贯,不如自己主动 ...

  7. idea推送代码忽略指定文件,文件夹配置

    idea推送代码忽略指定文件,文件夹配置 今天碰到一个问题,配置了.gitignore文件后没有生效,整了半天,最后发现一种直接配置的方法,可以指定文件夹,或者指定文件类型 打开设置

  8. C语言:计算长方形面积问题

    #include <stdio.h> #include <stdlib.h> /* run this program using the console pauser or a ...

  9. .NET 代理模式(一)基本概念

    代理模式 代理模式,它是一种结构型的设计模式. 让你能够提供对象的替代品或其占位符. 代理控制着对于原对象的访问, 并允许在将请求提交给对象前后进行一些处理. 简单理解就是 客户端不会直接与实际实现类 ...

  10. 用【Makefile】或【Cmake】编译【C/Fortran】程序文件

    一.vimrc文件设置 set tabstop=4 "tab空格4 set expandtab "将tab扩展成空格 set softtabstop=4 "表示在编辑模式 ...