当前位置: 首页 > news >正文

高性能渲染——详解Html Canvas的优势与性能

本文由葡萄城技术团队原创并首发。转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。

一、什么是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在计算与渲染上的作用。

七. 参考文章

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

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

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

扩展链接:

Redis从入门到实践

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

Chrome开发者工具使用教程

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

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

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

相关文章:

高性能渲染——详解Html Canvas的优势与性能

本文由葡萄城技术团队原创并首发。转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 一、什么是Canvas 想必学习前端的同学们对Canvas 都不陌生,它是 HTML5 新增的“画布”元素&#x…...

2023.10 各个编程语言 受欢迎指数 排行

目录 一、前言: 二、排行: 三、趋势: 四、历史排名: 五、名人堂: 一、前言: 来自tiobe...

『PyQt5-基本控件』| 15 如何设置主窗口居中?退出应用程序如何操作?

15 如何设置主窗口居中?退出应用程序如何操作? 1 如何实现主窗口居中显示?1.1 获取屏幕坐标1.2 获取窗口坐标1.3 居中计算1.4 移动位置1.5 完整代码1.6 效果演示2 如何退出应用程序?2.1 使用按钮退出2.2 信号与槽绑定2.3 布局和增加按钮2.4 定义一个按钮事件2.5 完整代码2.…...

scrapy+selenium框架模拟登录

目录 一、cookie和session实现登录原理 二、模拟登录方法-Requests模块Cookie实现登录 三、cookiesession实现登录并获取数据 四、selenium使用基本代码 五、scrapyselenium实现登录 一、cookie和session实现登录原理 cookie:1.网站持久保存在浏览器中的数据2.可以是长期…...

【实验五】题解

T1:缺失的数字 题目描述; 我是敦立坤的爹!!! 一个整数集合中含有n个数字,每个数字都在0n之间。假设0n的n1个数字中有且仅有一个数字不在该集合中,请找出这个数字。 分析: 这里引用一个桶的思…...

Android开发知识学习——Kotlin基础

函数声明 声明函数要用用 fun 关键字,就像声明类要用 class 关键字一样 「函数参数」的「参数类型」是在「参数名」的右边 函数的「返回值」在「函数参数」右边使用 : 分隔,没有返回值时可以省略 声明没有返回值的函数: fun main(){println…...

C++——定义一个 Book(图书)类

完整代码: /*定义一个 Book(图书)类,在该类定义中包括数据成员和成员函数 数据成员:book_name (书名)、price(价格)和 number(存书数量); 成员函数:display()显示图书的 情况;borro…...

深度学习之基于YoloV5的道路地面缺陷检测系统(UI界面)

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介 二、功能三、道路地面缺陷检测系统四. 总结 一项目简介 基于YoloV5的道路地面缺陷检测系统利用深度学习中的目标检测算法,特别是YoloV5算法&am…...

AcWing94. 递归实现排列型枚举:输出1~n的全排列

题目 把 1∼ n n n 这 n n n 个整数排成一行后随机打乱顺序,输出所有可能的次序。 输入格式 一个整数 n n n。 输出格式 按照从小到大的顺序输出所有方案,每行 1 个。 首先,同一行相邻两个数用一个空格隔开。 其次,对于两…...

神经网络多种注意力机制原理和代码讲解

多种注意力表格: 大神参考仓库链接: 魔鬼面具 对应 name 就是目录,点击即可跳转到对应学习。 nameneed_chaneelpaper SE (2017) Truehttps://arxiv.org/abs/1709.01507 BAM (2018) Truehttps://arxiv.org/pdf/1807.06514.pdf CBAM (2018) Tr…...

前端HTML

文章目录 一、什么是前端前端后端 前端三剑客1.什么是HTML2.编写前端的步骤1.编写服务端2.浏览器充当客户端访问服务端​ 3.浏览器无法正常展示服务端内容(因为服务端的数据没有遵循标准)4.HTTP协议>>>:最主要的内容就是规定了浏览器与服务端之间数据交互的格式 3. 前…...

Jenkins安装(Jenkins 2.429)及安装失败解决(Jenkins 2.222.4)

敏捷开发与持续集成 敏捷开发 敏捷开发以用户的需求进化为核心,采用迭代、循序渐进的方法进行软件开发。在敏捷开发中,软件项目在构建初期被切分成多个子项目,各个子项目的成果都经过测试,具备可视、可集成和可运行使用的特征。…...

vue中哪些数组操作可以重排

以下是Vue中可以重排数组的常用方法的示例: push():在数组末尾添加一个或多个元素 // 初始化数组 let myArray [1, 2, 3]; // 在数组末尾添加一个元素4 myArray.push(4); console.log(myArray); // [1, 2, 3, 4] // 在数组末尾添加多个元素5和6 myArr…...

订单创建订单确认、收货创建收货确认取消收货、生成库存和领用单发料

本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:山JAVA开发王大师,专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯 山峯 转载说明:务必注明来源(注明:作者:王文…...

yolox转rknn

使用瑞芯微版本的yolox:https://github.com/airockchip/YOLOXpip install torch1.8.1 torchvision0.9.1 torchaudio0.8.1 --no-cache -i https://pypi.tuna.tsinghua.edu.cn/simplepip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple --…...

llava1.5模型安装、预测、训练详细教程

引言 本博客介绍LLava1.5多模态大模型的安装教程、训练教程、预测教程,也会涉及到hugging face使用与wandb使用。 源码链接:点击这里 demo链接:点击这里 论文链接:点击这里 一、系统环境 ubuntu 20.04 gpu: 2*3090 cuda:11.6 二、LLava环境安装 1、代码下载…...

一个ppt带你读懂网络安全行业四大顶会之一的ndss论文<<Large Language Model guided Protocol Fuzzing>>

论文下载地址: Large Language Model guided Protocol Fuzzing...

ajax调用springboot后台接口

工具 api测试工具 由于后台接口不是同一个团队编写的,在文档缺失的情况下,需要测试后台接口接收参数类型,可以使用这个工具,注册很方便 页面如下所示,可以选择请求方法是get,或者post 重点介绍两种&…...

2021-arxiv-LoRA Low-Rank Adaptation of Large Language Models

2021-arxiv-LoRA Low-Rank Adaptation of Large Language Models Paper: https://arxiv.org/abs/2106.09685 Code: https://github.com/microsoft/LoRA 大型语言模型的LoRA低秩自适应 自然语言处理的一个重要范式包括对通用领域数据的大规模预训练和对特定任务或领域的适应。…...

dockefile

文章目录 应用的部署MySql的部署Tomcat的部署 dockerfileDocker原理镜像的制作容器转镜像Dockerfile 服务编排Docker Compose Docker 私有仓库 应用的部署 搜索app的镜像拉去app的镜像创建容器操作容器中的app MySql的部署 容器内的网络服务和外部机器无法直接通信外部机器和…...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

C#学习第29天:表达式树(Expression Trees)

目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...

xmind转换为markdown

文章目录 解锁思维导图新姿势:将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件(ZIP处理)2.解析JSON数据结构3:递归转换树形结构4:Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...

​​企业大模型服务合规指南:深度解析备案与登记制度​​

伴随AI技术的爆炸式发展,尤其是大模型(LLM)在各行各业的深度应用和整合,企业利用AI技术提升效率、创新服务的步伐不断加快。无论是像DeepSeek这样的前沿技术提供者,还是积极拥抱AI转型的传统企业,在面向公众…...