SVG和HTML5 Canvas有什么区别?

99

SVG和HTML5 Canvas之间有什么区别?在我看来,它们似乎做同样的事情。基本上,它们都使用坐标点绘制矢量图。

我错过了什么?SVG和HTML5 Canvas之间主要的区别是什么?为什么我应该选择一个而不是另一个?


4
维基百科上有一篇有用的文章:Canvas与可缩放矢量图形(SVG)的比较 - Rudu
据我所知,Canvas不支持矢量图形,它只能处理位图。 - Bobby Jack
可能是HTML5 Canvas vs SVG/VML?的重复问题。 - Phrogz
Canvas是栅格图形,而SVG是可缩放的矢量图形。SitePoint链接提供了最佳解释:https://www.sitepoint.com/canvas-vs-svg-choosing-the-right-tool-for-the-job/ - MechaCode
10个回答

54

SVG就像一个“绘画”程序。每个形状都有它的绘制指令,形状的任何部分都可以更改。绘图是面向形状的。

Canvas就像一个“绘制”程序。一旦像素绘制到屏幕上,那就是你的绘画结果。你不能改变形状,除非用其他像素覆盖它们。绘画是面向像素的。

对于某些程序来说,能够更改绘图非常重要;例如草图应用程序、图表工具等。因此,在这方面SVG具有优势。

对于某些艺术类程序而言,控制单个像素很重要。

使用Canvas比SVG更容易通过鼠标拖动进行用户操作的流畅动画效果。

计算机屏幕上的一个像素通常需要占用4个字节的信息,现在的电脑屏幕需要几兆字节。因此,如果您想让用户编辑图像然后再次上传它,则使用Canvas可能会不方便。

相比之下,使用SVG绘制涵盖整个屏幕的少量形状仅占用少量字节,下载速度快,并且可以轻松地使用相同的优势重新上传。因此,SVG比Canvas更快。

谷歌使用SVG实现了Google Maps。这为网络应用程序带来了流畅的性能和平滑的滚动效果。


21
不会给你负面评价- 新版谷歌地图现在使用画布(canvas)而不是SVG了。 SVG版本现已弃用。 - Duniyadnd

44
请参考维基百科:http://en.wikipedia.org/wiki/Canvas_element

SVG是浏览器中绘制形状的早期标准。然而,由于每个绘制的形状在场景图或DOM中都作为对象被记忆下来,并随后呈现为位图,因此SVG处于一个根本性更高的级别。这意味着如果一个SVG对象的属性被更改,浏览器可以自动重新呈现场景。

在上面的示例中,一旦矩形被绘制,系统就会忘记它被绘制了。如果它的位置发生改变,则整个场景都需要被重新绘制,包括任何可能被矩形覆盖的对象。但在等效的SVG情况下,可以简单地更改矩形的位置属性,浏览器将确定如何重新绘制它。还可以在画布中分层绘制,然后重新创建特定层。

SVG图像以XML表示,可以使用XML编辑工具创建和维护复杂场景。

SVG场景图使事件处理程序与对象相关联,所以矩形可以响应onClick事件。要在canvas中获得相同的功能,必须手动将鼠标单击的坐标与绘制的矩形的坐标匹配,以确定是否单击了它。

从概念上讲,canvas是可以构建SVG的较低级协议。[需要引证]然而,通常情况下不是这样——它们是独立的标准。情况很复杂,因为Canvas有场景图库,并且SVG具有一些位图操作功能。

更新:

我使用SVG是因为它具有标记语言的能力,可以通过XSLT进行处理,并且可以在其节点中保持其他标记。同样,我可以在我的标记(化学)中保留SVG。这使我可以通过标记的组合来操作SVG属性(例如呈现)。虽然Canvas可能也可以实现这一点,但我怀疑它会更加困难。

2
最后一段的最后一句话也需要引用一两个来源。SVG没有“位图操作功能”,除非作者试图将SVG滤镜效果误传为该功能,但是其意思并不清楚。 - Erik Dahlström
@Erik 我同意你的看法。看起来这篇 WP 条目需要编辑。 - peter.murray.rust
听起来对于大多数应用程序而言,SVG优于Canvas。这是真的吗?Canvas有什么SVG做不到的吗? - mcv
我知道这已经过去了很多年,但是今天有许多画布库,比如paper.js和fabric.js。 - lesolorzanov
SVG对性能不利,因为它使用真实的DOM来更新对象,导致回流;Canvas对使用也不利,因为它不能将对象作为单独的实体进行跟踪。如果我们有一个使用虚拟DOM的Canvas会怎样呢? - PirateApp

39

Canvas与SVG的高级概述

Canvas

  1. 基于像素(动态.png)
  2. 单个HTML元素(在开发者工具中检查元素。您只能看到canvas标签)
  3. 仅通过脚本修改
  4. 事件模型/用户交互是粒度化的(x,y)
  5. 性能更好的情况是表面较小、对象数量较大(> 10k),或两者兼备

SVG

  1. 基于形状
  2. 多个图形元素,成为DOM的一部分
  3. 通过脚本和CSS进行修改
  4. 事件模型/用户交互是抽象的(rect,path)
  5. 性能更好的情况是对象数量较少(<10K)、表面较大或两者兼备

详细差异请参阅http://msdn.microsoft.com/en-us/library/ie/gg193983(v=vs.85).aspx


24

它们的区别在于它们是什么以及它们为您提供了什么。

  • SVG是可缩放矢量图形的文档格式。
  • Canvas是用于将矢量图形绘制到特定大小位图的JavaScript API。

稍微详细解释一下,格式与API的区别:

使用SVG,您可以在许多不同的工具中查看、保存和编辑文件。使用Canvas只需绘制,除了屏幕上生成的图片外,没有保留任何有关您刚刚所做的内容。您可以对两者进行动画处理,SVG通过查看指定的元素和属性来处理重新绘制,而使用Canvas则必须使用API自己重新绘制每个帧。您可以缩放两者,但SVG会自动缩放,而使用Canvas再次需要为给定大小重新发出绘图命令。


1
也许是所有答案中最公正和技术上准确的。SVG是一种文档格式,可以在服务器上创建(大多数是静态的)或在客户端本身上创建。画布框架只是图片,因此自然需要重新绘制,具有其API。 - user568109

11

对于SVG和Canvas,我印象最深刻的两点是:

1. Canvas可以在没有DOM的情况下使用,而SVG严重依赖于DOM,在复杂度增加时性能会变慢。比如在游戏设计中。

2. 使用SVG的优势在于分辨率在各个平台上保持不变,而Canvas则缺乏这一点。

更多详细信息请参阅此网站:http://dev.opera.com/articles/view/svg-or-canvas-choosing-between-the-two/


4

这完全取决于您的需求。

  • 如果您只想在屏幕上显示图像/图表,则推荐使用canvas。 (例如PNG,GIF,BMP等)

  • 如果您想扩展图形的功能,例如如果您在图表上悬停鼠标想要缩放某个区域而不会破坏显示质量,则选择SVG。(好的例子是AutoCAD,Visio,GIS文件)。

如果您想构建具有形状连接器的动态流程图创建工具,则最好选择SVG而不是CANVAS。

  • 当屏幕尺寸增加时,canvas开始退化,因为需要绘制更多像素。

  • 当屏幕上的对象数量增加时,SVG会开始退化,因为我们不断将它们添加到DOM中。

还请参考:http://msdn.microsoft.com/en-us/library/gg193983(v=vs.85).aspx


3

SVG

SVG(可缩放矢量图形)基于使用情景,用于制作标志、图表等。由于它是矢量图形,您可以绘制后忘记它。当视口改变时(如重新调整大小或缩放),它会自动调整而无需重新绘制。

Canvas

Canvas是一种位图(或光栅图),通过将像素绘制到屏幕上实现。它用于开发游戏或图形体验(https://www.chromeexperiments.com/webgl),在给定的区域内绘制像素并通过重新绘制更改。由于它是光栅类型,因此需要完全重新绘制以适应视口变化。

参考资料

http://www.sitepoint.com/7-reasons-to-consider-svgs-instead-of-canvas

http://en.wikipedia.org/wiki/WebGL

http://vector-conversions.com/vectorizing/raster_vs_vector.html


2
SVG是一种类似文件格式的绘图规范。它是一个文档,就像HTML文件一样,你可以交换SVG文件。此外,由于SVG元素和HTML元素共享相同的DOM API,因此可以使用JavaScript以与创建HTML DOM相同的方式生成SVG DOM。但是,你不需要JavaScript来生成SVG文件,只需使用简单的文本编辑器即可编写SVG。但是,在绘制中需要至少一个计算器来计算形状的坐标。 CANVAS仅是一个绘图区域。必须使用JavaScript生成画布的内容。你不能交换canvas,它没有文档。而且画布的元素不是DOM树的一部分,因此无法使用DOM API来操作画布的内容。相反,必须使用专用的canvas API将形状绘制到画布上。 SVG的优点是可以将绘图作为文档进行交换。而CANVAS的优点是具有更少冗长的JavaScript API来生成内容。
以下是一个示例,展示了可以实现类似的结果,但在JavaScript中执行的方式非常不同。

// Italic S in SVG

(function () {

  const ns='http://www.w3.org/2000/svg';
  let s = document.querySelector('svg');
  let p = document.createElementNS (ns, 'path');
  p.setAttribute ('id', 'arc');
  p.setAttribute ('d', 'M 0.9 -0.9 a 0.8,0.4 -10 0,0 -0.9,0.9');
  s.appendChild (p);
  let u = document.createElementNS (ns, 'use');
  u.setAttribute ('href', '#arc');
  u.setAttribute ('transform', 'rotate(180)');
  s.appendChild (u);

})();

// Italic S in CANVAS

(function () {

  let c = document.querySelector('canvas');
  let w = c.width = c.clientWidth;
  let h = c.height = c.clientHeight;
  let x = c.getContext('2d');
  x.lineWidth = 0.05 * w;
  x.moveTo (w/2, h/2);
  x.bezierCurveTo (w*0.02, h*0.4,
                   w*0.4, -h*0.02,
                   w*0.95, h*0.05);
  x.moveTo (w/2, h/2);
  x.bezierCurveTo (w*(1-0.02), h*(1-0.4),
                   w*(1-0.4), h*(1+0.02),
                   w*(1-0.95), h*(1-0.05));
  x.stroke();

})();
svg, canvas {
  width: 3em;
  height: 3em;
}

svg {
  vertical-align: text-top;
  stroke: black;
  stroke-width: 0.1;
  fill: none;
}

canvas {
  vertical-align: text-bottom;
}

div {
  float: left;
}
<div><svg viewBox="-1 -1 2 2"></svg>VG</div>
<div>CANVA<canvas></canvas></div>

正如你所看到的,结果几乎相同,但JavaScript代码完全不同。SVG使用DOM API创建,使用createElement、setAttribute和appendChild。所有图形都在属性字符串中。SVG具有更强大的基元。例如,CANVAS没有等效于SVG圆弧路径的内容。 CANVAS示例尝试用Bezier曲线模拟SVG圆弧。在SVG中,您可以重用元素以便转换它们。在CANVAS中,您不能重用元素。相反,您必须编写JavaScript函数以便调用它两次。SVG具有viewBox,允许使用归一化坐标,简化旋转。在CANVAS中,您必须根据clientWidth和clientHeight自己计算坐标。您可以使用CSS样式所有SVG元素。在CANVAS中,您无法使用CSS样式任何内容。因为SVG是一个DOM,您可以为所有SVG元素分配事件处理程序。CANVAS中的元素没有DOM和DOM事件处理程序。但另一方面,CANVAS代码更易于阅读。您不需要关心XML名称空间。并且您可以直接调用图形函数,因为您不需要构建DOM。教训很清楚:如果您想快速绘制一些图形,请使用CANVAS。如果您需要共享图形,例如使用CSS进行样式设置或希望在图形中使用DOM事件处理程序,请构建SVG。

1

除了上述要点之外:

与JPEG、GIF等相比,SVG在网页传输时更轻量级,并且在缩放时能够保持极高的质量。


1

SVG
SVG基于对象模型。
适用于使用大渲染区域。
SVG提供事件处理程序的任何支持。
允许通过脚本和CSS进行修改。
SVG具有更好的可伸缩性。
SVG是矢量基础(由形状组成)。
SVG不适用于游戏图形。
SVG不依赖分辨率。
SVG能够进行API动画。
SVG适合高质量和任何分辨率的打印。

Canvas元素

Canvas基于像素。
适用于使用小渲染区域。
Canvas不提供任何事件处理程序资源。
只允许通过脚本进行修改。
Canvas具有较差的可伸缩性。
Canvas基于光栅(由像素组成)。
Canvas适用于游戏图形。
Canvas完全依赖分辨率。
Canvas没有任何API用于动画。
Canvas不适合打印高质量和高分辨率。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接