HTML5 Canvas和SVG都是基于标准的HTML5技术,可用于创建令人惊叹的图形和视觉体验。本文探讨的问题是:在项目中选择使用哪一个真的重要吗?换句话说,是否存在某些情况更倾向于使用HTML5 Canvas而不是SVG?
首先,让我们简要介绍HTML5 Canvas和SVG。
什么是HTML5 Canvas?
canvas
元素为脚本提供了一个分辨率相关的位图画布,可用于实时渲染图形、游戏画面、艺术作品或其他视觉图像。
换言之,<canvas>
标签暴露了一个表面,你可以通过JavaScript编程接口逐像素地创建和操作光栅化图像。
以下是一个基本代码示例:
HTML部分:
<canvas id="myCanvas" width="800" height="800"></canvas>
JavaScript部分:
const canvas = document.getElementById('myCanvas');
const context = canvas.getContext('2d');
context.fillStyle = '#c00';
context.fillRect(10, 10, 100, 100);
通过获取2D上下文对象的引用,你可以利用HTML5 Canvas API的方法和属性。在上面的例子中,我绘制了一个简单的红色方块,大小为100 x 100像素,距离<canvas>
绘图表面左侧和顶部各10px。
由于分辨率依赖性,您在<canvas>
上创建的图像在放大或显示在Retina显示屏上时可能会损失质量。
绘制简单形状只是冰山一角。HTML5 Canvas API允许您绘制弧线、路径、文本、渐变等。您还可以逐像素地操作您的图像。这意味着您可以在图形的某些区域中将一种颜色替换为另一种颜色,可以动画化您的绘图,甚至可以将视频绘制到画布上并改变其外观。
SVG是什么?
SVG代表可缩放矢量图形。根据规范:
SVG是一种描述二维图形的语言。作为独立格式或在与其他XML混合时,它使用XML语法。与HTML5混合时,它使用HTML5语法。……
SVG绘图可以是交互式的和动态的。动画可以声明性地定义(即,通过在SVG内容中嵌入SVG动画元素)或通过脚本来触发。
SVG是一种设计用于创建矢量图形的XML文件格式。作为可缩放的,其优势在于允许您在保持清晰度和高质量的同时增大或减小矢量图像的大小。(这对于HTML5 Canvas生成的图像无法实现。)
以下是使用SVG绘制的相同红色方块(之前使用HTML5 Canvas创建):
<svg xmlns="https://www.w3.org/2000/svg" viewbox="0 0 600 600">
<desc>Red rectangle shape</desc>
<rect x="10" y="10" width="100" height="100" fill="#c00" />
</svg>
使用SVG,你几乎可以实现Canvas能做的所有事情——比如绘制形状和路径、应用渐变和图案、实现动画等。然而,这两种技术的工作原理有着根本的不同。与基于Canvas的图形不同,SVG拥有DOM,因此CSS和JavaScript都可以对其进行访问。例如,你可以使用CSS改变SVG图形的外观,通过CSS或JavaScript对其节点进行动画处理,使其部分像<div>
一样响应鼠标或键盘事件。随着后续章节的深入,这种差异在你为项目选择Canvas还是SVG时将起到关键作用。
立即模式与保留模式
区分立即模式和保留模式至关重要。HTML5 Canvas属于前者,SVG属于后者。
立即模式意味着,一旦你的绘图出现在Canvas上,Canvas就不再跟踪它。换句话说,作为开发者,你需要自行计算绘制对象的命令,创建并维护最终输出应呈现的模型或场景,并指定需要更新的内容。浏览器的图形API仅负责将你的绘图命令传达给浏览器,由浏览器执行这些命令。
SVG采用保留模式,您只需发出绘制指令,描述希望在屏幕上显示的内容,浏览器的图形API会创建一个内存模型或场景,代表最终输出,并将其转换为浏览器所需的绘图命令。
相比之下,Canvas作为即时图形系统,不具备DOM(文档对象模型)。在Canvas中,您绘制像素后,系统便不再保留这些像素的信息,从而减少了维持内部绘图模型所需的额外内存。而在SVG中,每次绘制的对象都会被添加到浏览器的内部模型中,这虽然使得开发者的操作更为简便,但也在性能上有所牺牲。
基于即时模式与保留模式的区别,以及其他Canvas和SVG各自的特点,我们可以概述出某些情况下,选择其中一种技术可能更符合项目目标。
HTML5 Canvas:利弊
HTML5 Canvas规范明确建议作者在有其他更合适手段可用时,不应使用<canvas>
元素。
例如,对于图形丰富的<header>
元素,最佳工具是HTML和CSS,而非<canvas>
(同样,SVG也不是最佳选择)。Zim JS canvas框架的创建者和创始人Dr Abstract也赞同这一观点,他写道:
DOM及DOM框架擅长展示信息,尤其是文本信息。相比之下,canvas则更像是一幅画。虽然可以在canvas上添加文本并使其响应式,但这些文本不像在DOM中那样便于选择或搜索。对于长滚动页面包含大量文本或图文混合的内容,DOM无疑是最佳选择。DOM非常适合社交媒体网站、论坛、购物平台以及我们日常使用的各种信息类应用。——“何时使用JavaScript Canvas库或框架”
因此,这是一个明确的不应使用<canvas>
的例子。那么,何时<canvas>
才是合适的选择呢?
Sarah Drasner的这条推文概述了canvas特性和能力的主要优缺点,有助于我们确定这项强大技术的适用场景:
I had this slide in a lot of talks and workshops over the years: pic.twitter.com/4K0C7mNzg2
— Sarah Drasner (@sarah_edo) October 2, 2019
您可以点击此处查看推文中的图片。
HTML5 Canvas的绝佳用途
Alvin Wan针对Canvas和SVG在性能方面进行了基准测试,既考虑了绘制对象的数量,也考虑了对象大小或canvas本身的大小。他总结的结果如下:
综上所述,当处理成百上千的对象时,DOM渲染的开销更为显著;在这种情况下,Canvas无疑是更优选择。然而,Canvas和SVG对于对象大小都是不变的。综合考量,Canvas在性能上明显占优。
基于我们对Canvas的了解,特别是它在绘制大量对象时表现出的卓越性能,以下是一些可能适用Canvas甚至优于SVG的场景。
游戏与生成艺术
对于图像密集型、高度互动的游戏以及生成艺术,Canvas通常是首选。
光线追踪
光线追踪是一种用于创建3D图形的技巧。
光线追踪通过追踪光线在图像平面中通过像素的路径,并模拟其与虚拟对象相遇的效果,来丰富图像。……光线追踪所达到的效果,……从……将原本简单的矢量图形转化为逼真的图像,到应用类似照片的滤镜以消除红眼。——SVG与Canvas:如何选择,微软文档。
如果你感到好奇,这里有一个由Mark Webster演示的光线追踪应用程序。
然而,尽管HTML5 Canvas无疑比SVG更适合这项任务,但这并不意味着光线追踪在<canvas>
元素上执行就是最佳选择。实际上,这可能会给CPU带来相当大的压力,以至于浏览器可能会停止响应。
在小表面上绘制大量对象
另一个例子是,当你的应用程序需要在一个相对较小的表面上绘制大量对象时,比如非交互式的实时数据可视化,如天气模式的图形表示。
上图来自这篇MSDN文章,这是我为此文进行研究的一部分。
视频中的像素替换
正如HTML5 Doctor文章中所展示的,Canvas适用的另一个场景是在视频中替换背景颜色,将其改为不同的颜色、场景或图像。
HTML5 Canvas不那么擅长的领域
另一方面,与SVG相比,Canvas在某些情况下可能不是最佳选择。
可扩展性
在多数需要可扩展性的场景中,使用SVG而非Canvas将更为合适。例如,高保真、复杂的图形,如建筑与工程图、组织结构图、生物学图解等,都是这类应用的典型例子。
通过SVG绘制的图像,在放大或打印时能保持极高的细节质量。此外,这些文档还能从数据库生成,使得SVG的XML格式在此任务中极为适用。
同时,这些图形通常具有交互性。以在线预订机票时的座位图为例,这正是SVG这类保留图形系统的一个绝佳应用场景。
尽管如此,借助如CreateJS和扩展了CreateJS的Zim等优秀库,开发者能够相对迅速地为其Canvas作品集成鼠标事件、命中测试、多点触控手势、拖放功能、控制元素等。
可访问性
虽然可以通过一些措施提高Canvas图形的可访问性——一个如Zim般优秀的Canvas库在此能加速这一过程——但在可访问性方面,Canvas并不突出。Canvas上绘制的内容仅是一系列像素,无法被辅助技术或搜索引擎机器人读取或解释。这又是SVG占优的领域:SVG本质上是XML,对人和机器都具有可读性。
不依赖JavaScript
如果你不想在你的应用中使用JavaScript,那么Canvas可能不是你的最佳选择。实际上,与<canvas>
元素交互的唯一方式就是通过JavaScript。相反,你可以使用Adobe Illustrator或Inkscape这样的标准矢量编辑程序来绘制SVG图形,并可以使用纯CSS来控制它们的外观,实现引人注目、微妙的动画和微交互。
结合HTML5 Canvas和SVG应对高级场景
有些情况下,通过结合HTML5 Canvas和SVG,你的应用可以兼得两者的优势。例如,一个基于Canvas的游戏可以使用矢量编辑程序生成的SVG图像作为精灵,以利用其可伸缩性和相比PNG图像更小的下载大小。或者一个绘图程序可以使用SVG设计其用户界面,并嵌入一个<canvas>
元素用于绘图。
最后,像Paper.js这样的强大库使得在HTML5 Canvas上脚本化矢量图形成为可能,从而为开发者提供了一种便捷的方式来同时使用这两种技术。
结论
在本文中,我探讨了HTML5 Canvas和SVG的一些关键特性,帮助你决定哪种技术可能最适合特定的任务。
答案是什么?
Chris Coyier同意Benjamin De Cock的观点,正如后者在推特上所说。
一个极其基本的回答是“当无法使用SVG时使用Canvas”(这里的“无法”可能意味着需要动画化数千个对象,或对每个像素进行单独操作等)。换言之,SVG应作为首选,Canvas则是备选方案。
— Benjamin De Cock (@bdc) October 2, 2019
Dr Abstract列出了一系列最适合使用Canvas构建的事物,包括交互式标识和广告、互动信息图、电子学习应用等。
在我看来,何时最好使用Canvas而非SVG并没有严格的规则。即时模式与保留模式的区别表明,在构建如图形密集型游戏等项目时,HTML5 Canvas无疑是优选;而对于扁平图像、图标和UI元素等,SVG则更为合适。然而,在这两者之间,HTML5 Canvas有扩展其应用范围的空间,尤其是考虑到各种强大的Canvas库能带来的便利。它们不仅使得在同一图形工作中同时使用这两种技术变得更加容易,而且使得一些原生Canvas项目中难以实现的功能——如交互控制和事件、响应性、可访问性特性等——现在大多数开发者都能轻松触及,这为HTML5 Canvas开辟了更多有趣应用的可能性。
关于Canvas与SVG的常见问题解答
Canvas和SVG的主要区别是什么?
Canvas和SVG都是用于创建图形的网络技术,但它们有一些关键区别。Canvas基于位图,即它与像素打交道。它非常适合创建复杂、交互式的图形,如游戏或其他需要动态视觉效果的应用程序。然而,一旦绘制了形状,除非重新绘制,否则无法更改。相比之下,SVG是基于矢量的方法。它使用形状和路径,并且每个对象在绘制后仍然可以操作。这使得SVG非常适合创建静态图形、标志和需要无损缩放的图标。
何时应该使用Canvas而不是SVG?
当需要创建复杂、交互式和高性能图形时,Canvas是最佳选择。这是因为Canvas处理像素,并允许直接操纵单个像素,使其非常适合实时视频处理或渲染大型数据集。但值得注意的是,Canvas不支持事件处理器,因此如果需要交互性,您必须自己实现。
何时SVG比Canvas更合适?
当需要创建无损缩放的图形,如标志或图标时,SVG是更好的选择。SVG还支持事件处理器,使得创建交互式图形更加容易。此外,SVG元素是DOM的一部分,这意味着它们可以像任何其他HTML元素一样,用CSS进行样式设置和用JavaScript进行操作。
我可以在同一个项目中同时使用Canvas和SVG吗?
是的,您可以在同一个项目中同时使用Canvas和SVG。实际上,结合使用两者有时会带来好处,因为它们各自有其优势和局限性。例如,您可能会在项目中需要复杂、交互式图形的部分使用Canvas,而在需要可缩放、静态图形的部分使用SVG。
Canvas和SVG的浏览器支持情况如何比较?
Canvas和SVG都拥有出色的浏览器支持。它们被所有现代浏览器,包括Chrome、Firefox、Safari和Edge所支持。然而,如果您需要支持旧版浏览器,值得注意的是SVG存在的时间更长,因此对旧版浏览器的兼容性略好。
Canvas和SVG如何处理动画?
Canvas和SVG都可以用于创建动画,但它们处理动画的方式不同。使用Canvas时,您需要手动清除并重绘每一帧的画布。而使用SVG,您可以通过CSS或JavaScript来动画化SVG元素,这通常更简单且效率更高。
Canvas和SVG对页面加载时间有何影响?
页面加载时间的影响取决于您创建的图形的复杂度和大小。对于复杂的、交互式图形,Canvas可能更快,因为它不需要为每个对象维护DOM。然而,对于简单的、静态图形,SVG可能更快,因为它不需要每次变化时都重绘整个图形。
我可以在Canvas和SVG中使用CSS吗?
SVG元素是DOM的一部分,因此你可以像任何其他HTML元素一样用CSS对其进行样式设置。相比之下,Canvas是一个位图,不支持CSS样式。不过,你可以使用CSS来设置Canvas元素本身的样式,例如设置其背景颜色或边框。
Canvas和SVG如何处理响应性?
SVG天生具有响应性,因为它是一种基于矢量的格式,因此缩放时不会损失质量。而Canvas并非天生响应,因为它基于位图格式。然而,你可以通过使用JavaScript根据视口大小调整其尺寸来使Canvas具有响应性。
我该如何选择Canvas和SVG用于我的项目?
选择Canvas还是SVG取决于项目的具体需求。考虑诸如所需图形的复杂性和交互性、对可扩展性和响应性的需求、浏览器支持以及你对这些技术的熟悉程度等因素。在某些情况下,同时使用Canvas和SVG可能更有益。