Javascript HTML5 Canvas vs. SVG vs. div

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5882716/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 19:21:01  来源:igfitidea点击:

HTML5 Canvas vs. SVG vs. div

javascripthtmlsvghtml5-canvas

提问by verdy

What is the best approach for creating elements on the fly and being able to move them around? For example, let's say I want to create a rectangle, circle and polygon and then select those objects and move them around.

动态创建元素并能够移动它们的最佳方法是什么?例如,假设我想创建一个矩形、圆形和多边形,然后选择这些对象并四处移动它们。

I understand that HTML5 provides three elements that can make this possible: svg, canvasand div. For what I want to do, which one of those elements will provide the best performance?

我知道 HTML5 提供了三个可以实现这一点的元素:svgcanvasdiv。对于我想做的事情,这些元素中的哪一个将提供最佳性能?

To compare these approaches, I was thinking of creating three visually identical web pages that each have a header, footer, widget and text content in them. The widget in the first page would be created entirely with the canvaselement, the second entirely with the svgelement, and the third with the plain divelement, HTML and CSS.

为了比较这些方法,我想创建三个视觉上相同的网页,每个网页都有页眉、页脚、小部件和文本内容。第一个页面中的小部件将完全用canvas元素创建,第二个完全用svg元素创建,第三个用普通div元素、HTML 和 CSS 创建。

回答by Simon Sarris

The short answer:

简短的回答:

SVG would be easierfor you, since selection and moving it around is already built in. SVG objects are DOM objects, so they have "click" handlers, etc.

SVG对您来说会更容易,因为已经内置了选择和移动它。SVG 对象是 DOM 对象,因此它们具有“单击”处理程序等。

DIVs are okay but clunky and have awfulperformance loading at large numbers.

资料核实是不错,但笨重,具有可怕的大量性能负载。

Canvas has the best performance hands-down, but you have to implement all concepts of managed state (object selection, etc) yourself, or use a library.

Canvas 具有最佳性能,但您必须自己实现托管状态(对象选择等)的所有概念,或者使用库。



The long answer:

长答案:

HTML5 Canvas is simply a drawing surface for a bit-map. You set up to draw (Say with a color and line thickness), draw that thing, and then the Canvas has no knowledge of that thing: It doesn't know where it is or what it is that you've just drawn, it's just pixels. If you want to draw rectangles and have them move around or be selectable then you have to code all of that from scratch, includingthe code to remember that you drew them.

HTML5 Canvas 只是位图的绘图表面。您设置绘制(比如使用颜色和线条粗细),绘制那个东西,然后 Canvas 不知道那个东西:它不知道它在哪里或您刚刚绘制的是什么,它是只是像素。如果您想绘制矩形并让它们四处移动或可选择,那么您必须从头开始编写所有这些代码,包括记住您绘制它们的代码。

SVG on the other hand must maintain references to each object that it renders. Every SVG/VML element you create is a real element in the DOM. By default this allows you to keep much better track of the elements you create and makes dealing with things like mouse events easier by default, but it slows down significantly when there are a large number of objects

另一方面,SVG 必须维护对它呈现的每个对象的引用。您创建的每个 SVG/VML 元素都是 DOM 中的真实元素。默认情况下,这允许您更好地跟踪您创建的元素,并在默认情况下更轻松地处理诸如鼠标事件之类的事情,但是当有大量对象时它会显着减慢

Those SVG DOM references mean that some of the footwork of dealing with the things you draw is done for you. And SVG is faster when rendering really largeobjects, but slower when rendering manyobjects.

那些 SVG DOM 引用意味着处理您绘制的东西的一些步法已经为您完成。SVG 在渲染非常大的对象时速度更快,但在渲染多个对象时速度更慢。

A game would probably be faster in Canvas. A huge map program would probably be faster in SVG. If you do want to use Canvas, I have some tutorials on getting movable objects up and running here.

Canvas 中的游戏可能会更快。一个巨大的地图程序在 SVG 中可能会更快。如果你想用画布,我对获得可移动物体和运行一些教程在这里

Canvas would be better for faster things and heavy bitmap manipulation (like animation), but will take more code if you want lots of interactivity.

Canvas 更适用于更快的事物和繁重的位图操作(如动画),但如果您想要大量的交互性,则需要更多的代码。

I've run a bunch of numbers on HTML DIV-made drawing versus Canvas-made drawing. I could make a huge post about the benefits of each, but I will give some of the relevant results of my tests to consider for your specific application:

我在 HTML DIV 制作的绘图与 Canvas 制作的绘图上运行了大量数字。我可以写一篇关于每种方法的好处的大文章,但我会给出一些我的测试的相关结果,以考虑您的特定应用:

I made Canvas and HTML DIV test pages, both had movable "nodes." Canvas nodes were objects I created and kept track of in Javascript. HTML nodes were movable Divs.

我制作了 Canvas 和 HTML DIV 测试页面,它们都有可移动的“节点”。画布节点是我在 Javascript 中创建和跟踪的对象。HTML 节点是可移动的 Div。

I added 100,000 nodes to each of my two tests. They performed quite differently:

我向我的两个测试中的每一个添加了 100,000 个节点。他们的表现截然不同:

The HTML test tab took forever to load (timed at slightly under 5 minutes, chrome asked to kill the page the first time). Chrome's task manager says that tab is taking up 168MB. It takes up 12-13% CPU time when I am looking at it, 0% when I am not looking.

HTML 测试标签需要很长时间才能加载(时间略低于 5 分钟,chrome 第一次要求终止页面)。Chrome 的任务管理器说该标签占用了 168MB。当我看它时它占用 12-13% 的 CPU 时间,当我不看它时占用 0%。

The Canvas tab loaded in one second and takes up 30MB. It also takes up 13% of CPU time all of the time, regardless of whether or not one is looking at it. (2013 edit: They've mostly fixed that)

Canvas 选项卡在一秒钟内加载并占用 30MB。它也始终占用 13% 的 CPU 时间,无论是否有人查看它。(2013 年编辑:他们大多已修复)

Dragging on the HTML page is smoother, which is expected by the design, since the current setup is to redraw EVERYTHING every 30 milliseconds in the Canvas test. There are plenty of optimizations to be had for Canvas for this. (canvas invalidation being the easiest, also clipping regions, selective redrawing, etc.. just depends on how much you feel like implementing)

在 HTML 页面上拖动更流畅,这是设计所期望的,因为当前设置是在 Canvas 测试中每 30 毫秒重新绘制一次所有内容。为此,Canvas 有很多优化。(画布失效是最简单的,还有裁剪区域、选择性重绘等。只取决于你想实现的程度)

There is no doubt you could get Canvas to be faster at object manipulation as the divs in that simple test, and of course far faster in the load time. Drawing/loading is faster in Canvas and has far more room for optimizations, too (ie, excluding things that are off-screen is very easy).

毫无疑问,在那个简单的测试中,你可以让 Canvas 在对象操作上更快,作为 div,当然在加载时间上更快。Canvas 中的绘图/加载速度更快,并且还有更多优化空间(即,排除屏幕外的内容非常容易)。

Conclusion:

结论:

  • SVG is probably better for applications and apps with few items (less than 1000? Depends really)
  • Canvas is better for thousands of objects and careful manipulation, but a lot more code (or a library) is needed to get it off the ground.
  • HTML Divs are clunky and do not scale, making a circle is only possible with rounded corners, making complex shapes is possible but involves hundreds of tiny tiny pixel-wide divs. Madness ensues.
  • SVG 可能更适合项目较少的应用程序和应用程序(少于 1000?确实取决于)
  • Canvas 更适合数千个对象和仔细操作,但需要更多的代码(或库)来实现它。
  • HTML Div 笨重且无法缩放,只能用圆角制作圆形,制作复杂形状是可能的,但涉及数百个微小的像素宽 div。疯狂随之而来。

回答by knut

To add to this, I've been doing a diagram application, and initially started out with canvas. The diagram consists of many nodes, and they can get quite big. The user can drag elements in the diagram around.

除此之外,我一直在做一个图表应用程序,最初是从画布开始的。该图由许多节点组成,它们可以变得非常大。用户可以拖动图表中的元素。

What I found was that on my Mac, for very large images, SVG is superior. I have a MacBook Pro 2013 13" Retina, and it runs the fiddle below quite well. The image is 6000x6000 pixels, and has 1000 objects. A similar construction in canvas was impossible to animate for me when the user was dragging objects around in the diagram.

我发现在我的 Mac 上,对于非常大的图像,SVG 更胜一筹。我有一台 MacBook Pro 2013 13" Retina,它可以很好地运行下面的小提琴。图像是 6000x6000 像素,有 1000 个对象。当用户在画布中拖动对象时,画布中的类似结构无法为我制作动画图表。

On modern displays you also have to account for different resolutions, and here SVG gives you all of this for free.

在现代显示器上,您还必须考虑不同的分辨率,而 SVG 在这里免费为您提供所有这些。

Fiddle: http://jsfiddle.net/knutsi/PUcr8/16/

小提琴:http: //jsfiddle.net/knutsi/PUcr8/16/

Fullscreen: http://jsfiddle.net/knutsi/PUcr8/16/embedded/result/

全屏:http: //jsfiddle.net/knutsi/PUcr8/16/embedded/result/

var wiggle_factor = 0.0;
nodes = [];

// create svg:
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute('style', 'border: 1px solid black');
svg.setAttribute('width', '6000');
svg.setAttribute('height', '6000');

svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink",
    "http://www.w3.org/1999/xlink");

document.body.appendChild(svg);


function makeNode(wiggle) {
    var node = document.createElementNS("http://www.w3.org/2000/svg", "g");
    var node_x = (Math.random() * 6000);
    var node_y = (Math.random() * 6000);
    node.setAttribute("transform", "translate(" + node_x + ", " + node_y +")");

    // circle:
    var circ = document.createElementNS("http://www.w3.org/2000/svg", "circle");
    circ.setAttribute( "id","cir")
    circ.setAttribute( "cx", 0 + "px")
    circ.setAttribute( "cy", 0 + "px")
    circ.setAttribute( "r","100px");
    circ.setAttribute('fill', 'red');
    circ.setAttribute('pointer-events', 'inherit')

    // text:
    var text = document.createElementNS("http://www.w3.org/2000/svg", "text");
    text.textContent = "This is a test! ???";

    node.appendChild(circ);
    node.appendChild(text);

    node.x = node_x;
    node.y = node_y;

    if(wiggle)
        nodes.push(node)
    return node;
}

// populate with 1000 nodes:
for(var i = 0; i < 1000; i++) {
    var node = makeNode(true);
    svg.appendChild(node);
}

// make one mapped to mouse:
var bnode = makeNode(false);
svg.appendChild(bnode);

document.body.onmousemove=function(event){
    bnode.setAttribute("transform","translate(" +
        (event.clientX + window.pageXOffset) + ", " +
        (event.clientY + window.pageYOffset) +")");
};

setInterval(function() {
    wiggle_factor += 1/60;
    nodes.forEach(function(node) {

        node.setAttribute("transform", "translate(" 
                          + (Math.sin(wiggle_factor) * 200 + node.x) 
                          + ", " 
                          + (Math.sin(wiggle_factor) * 200 + node.y) 
                          + ")");        
    })
},1000/60);

回答by Leo The Four

Knowing the differences between SVG and Canvas would be helpful in selecting the right one.

了解 SVG 和 Canvas 之间的差异将有助于选择正确的。

Canvas

帆布

SVG

SVG

  • Resolution independent
  • Support for event handlers
  • Best suited for applications with large rendering areas (Google Maps)
  • Slow rendering if complex (anything that uses the DOM a lot will be slow)
  • Not suited for game application
  • 分辨率无关
  • 支持事件处理程序
  • 最适合具有大渲染区域的应用程序(谷歌地图)
  • 如果复杂,渲染速度会很慢(任何使用 DOM 的东西都会很慢)
  • 不适合游戏应用

回答by ümit

I agree with Simon Sarris's conclusions:

我同意 Simon Sarris 的结论:

I have compared some visualization in Protovis (SVG) to Processingjs (Canvas) which display > 2000 points and processingjs is much faster than protovis.

我将 Protovis (SVG) 中的一些可视化与 Processingjs (Canvas) 进行了比较,后者显示 > 2000 个点,并且 processingjs 比 protovis 快得多。

Handling events with SVG is of course much easer because you can attach them to the objects. In Canvas you have to do it manually (check mouse position, etc) but for simple interaction it shouldn't be hard.

使用 SVG 处理事件当然要容易得多,因为您可以将它们附加到对象上。在 Canvas 中,您必须手动完成(检查鼠标位置等),但对于简单的交互来说应该不难。

There is also the dojo.gfxlibrary of the dojo toolkit. It provides an abstraction layer and you can specify the renderer (SVG, Canvas, Silverlight). That might be also an viable choice although I don't know how much overhead the additional abstraction layer adds but it makes it easy to code interactions and animations and is renderer-agnostic.

还有dojo 工具包的dojo.gfx库。它提供了一个抽象层,您可以指定渲染器(SVG、Canvas、Silverlight)。这可能也是一个可行的选择,虽然我不知道额外的抽象层增加了多少开销,但它可以轻松编写交互和动画,并且与渲染器无关。

Here are some interesting benchmarks:

以下是一些有趣的基准测试:

回答by Erik Kaplun

Just my 2 cents regarding the divs option.

关于 divs 选项,我只需要 2 美分。

Famous/Infamous and SamsaraJS (and possibly others) use absolutely positioned non-nested divs (with non-trivial HTML/CSS content), combined with matrix2d/matrix3d for positioning and 2D/3D transformations, and achieve a stable 60FPS on moderate mobile hardware, so I'd argue against divs being a slow option.

著名/臭名昭著和 SamsaraJS(可能还有其他人)使用绝对定位的非嵌套 div(具有非平凡的 HTML/CSS 内容),结合 matrix2d/matrix3d 进行定位和 2D/3D 转换,并在中等移动硬件上实现稳定的 60FPS ,所以我反对 div 是一个缓慢的选择。

There are plenty of screen recordings on Youtube and elsewhere, of high-performance 2D/3D stuff running in the browser with everything being an DOM element which you can Inspect Elementon, at 60FPS (mixed with WebGL for certain effects, but not for the main part of the rendering).

Youtube 和其他地方有很多屏幕录像,在浏览器中运行的高性能 2D/3D 东西,所有东西都是一个 DOM 元素,你可以在 60FPS 上检查元素(与 WebGL 混合以获得某些效果,但不适用于渲染的主要部分)。

回答by Sebastian

While there is still some truth to most of the answers above, I think they deserve an update:

尽管上述大多数答案仍有一定的道理,但我认为它们值得更新:

Over the years the performance of SVG has improved a lot and now there is hardware-accelerated CSS transitions and animations for SVGthat do not depend on JavaScript performance at all. Of course JavaScript performance has improved, too and with it the performance of Canvas, but not as much as SVG got improved. Also there is a "new kid" on the block that is available in almost all browsers today and that is WebGL. To use the same words that Simon used above: It beats both Canvas and SVGhands down. This doesn't mean it should be the go-to technology, though, since it's a beast to work with and it is only faster in very specific use-cases.

多年来,SVG 的性能有了很大的提高,现在有硬件加速的 CSS 过渡和 SVG 动画,完全不依赖于 JavaScript 性能。当然,JavaScript 的性能也有所提高,Canvas 的性能也随之提高,但没有 SVG 的提高那么大。此外,目前几乎所有浏览器都可以使用该块上的“新孩子”,那就是WebGL。使用 Simon 上面使用的相同词:它击败了 Canvas 和 SVG。但是,这并不意味着它应该成为首选技术,因为它是一种可以使用的野兽,并且仅在非常特定的用例中速度更快。

IMHO for most use-cases today, SVG gives the best performance/usability ratio. Visualizations need to be really complex (with respect to number of elements) and really simple at the same time (per element) so that Canvas and even more so WebGL really shine.

恕我直言,对于当今的大多数用例,SVG 提供了最佳的性能/可用性比。可视化需要非常复杂(就元素数量而言),同时又非常简单(每个元素),这样 Canvas 甚至 WebGL 才能真正闪耀。

In this answer to a similar questionI am providing more details, why I think that the combinationof all three technologies sometimes is the best option you have.

这个对类似问题的回答中,我提供了更多细节,为什么我认为所有三种技术的组合有时是您拥有的最佳选择。

回答by Gaurav

For your purposes, I recommend using SVG, since you get DOM events, like mouse handling, including drag and drop, included, you don't have to implement your own redraw, and you don't have to keep track of the state of your objects. Use Canvas when you have to do bitmap image manipulation and use a regular div when you want to manipulate stuff created in HTML. As to performance, you'll find that modern browsers are now accelerating all three, but that canvas has received the most attention so far. On the other hand, how well you write your javascript is critical to getting the most performance with canvas, so I'd still recommend using SVG.

出于您的目的,我建议使用 SVG,因为您获得 DOM 事件,例如鼠标处理,包括拖放,包括在内,您不必实现自己的重绘,也不必跟踪状态你的对象。当您必须进行位图图像操作时使用 Canvas,当您想要操作在 HTML 中创建的内容时使用常规 div。至于性能,您会发现现代浏览器现在正在加速这三个方面,但到目前为止,画布受到了最多的关注。另一方面,您编写 javascript 的能力对于使用画布获得最大性能至关重要,因此我仍然建议使用 SVG。

回答by Alireza Fattahi

While googling I find a good explanation about usage and compression of SVGand Canvasat http://teropa.info/blog/2016/12/12/graphics-in-angular-2.html

在谷歌搜索时,我在http://teropa.info/blog/2016/12/12/graphics-in-angular-2.html找到了关于SVGCanvas 的使用和压缩的很好的解释

Hope it helps:

希望能帮助到你:

  • SVG, like HTML, uses retained rendering: When we want to draw a rectangle on the screen, we declaratively use a element in our DOM. The browser will then draw a rectangle, but it will also create an in-memory SVGRectElementobject that represents the rectangle. This object is something that sticks around for us to manipulate – it is retained. We can assign different positions and sizes to it over time. We can also attach event listeners to make it interactive.
  • Canvas uses immediate rendering: When we draw a rectangle, the browser immediately renders a rectangle on the screen, but there is never going to be any "rectangle object" that represents it. There's just a bunch of pixels in the canvas buffer. We can't move the rectangle. We can only draw another rectangle. We can't respond to clicks or other events on the rectangle. We can only respond to events on the whole canvas.

So canvas is a more low-level, restrictive API than SVG. But there's a flipside to that, which is that with canvas you can do more with the same amount of resources. Because the browser does not have to create and maintain the in-memory object graph of all the things we have drawn, it needs less memory and computation resources to draw the same visual scene. If you have a very large and complex visualization to draw, Canvas may be your ticket.

  • SVG 与 HTML 一样,使用保留渲染:当我们想在屏幕上绘制一个矩形时,我们会声明性地使用 DOM 中的一个元素。然后浏览器将绘制一个矩形,但它也会创建一个内存中的SVGRectElement对象来表示该矩形。这个对象是我们可以操纵的东西——它被保留了下来。随着时间的推移,我们可以为其分配不同的位置和大小。我们还可以附加事件侦听器以使其具有交互性。
  • Canvas 使用立即渲染:当我们绘制一个矩形时,浏览器会立即在屏幕上渲染一个矩形,但永远不会有任何“矩形对象”来表示它。画布缓冲区中只有一堆像素。我们不能移动矩形。我们只能绘制另一个矩形。我们无法响应矩形上的点击或其他事件。我们只能响应整个画布上的事件。

所以画布是一个比 SVG 更底层、更受限制的 API。但有一个反面,那就是使用画布,您可以使用相同数量的资源做更多的事情。因为浏览器不必创建和维护我们绘制的所有事物的内存对象图,所以它需要更少的内存和计算资源来绘制相同的视觉场景。如果您要绘制非常大且复杂的可视化,Canvas 可能是您的选择。