HTML5帆布与SVG与div

在dynamic创build元素并能够移动它们的最佳方法是什么? 例如,假设我想创build一个矩形,圆形和多边形,然后select这些对象并移动它们。

我知道HTML5提供了三个可以实现这一点的元素: svg , canvas和div 。 对于我想要做的,哪一个元素将会提供最好的性能?

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

简短的回答:

SVG对你来说更容易一些,因为select和移动它已经是内置的了.SVG对象是DOM对象,所以它们有“点击”处理程序等等。

DIV可以,但笨重,并有大量的可怕的性能加载。

canvas具有最好的性能,但是你必须自己实现pipe理状态(对象select等)的所有概念,或者使用一个库。


漫长的回答:

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

另一方面,SVG必须保持对呈现的每个对象的引用。 您创build的每个SVG / VML元素都是DOM中的一个真实元素。 默认情况下,这可以让您更好地跟踪所创build的元素,并且默认情况下更容易处理像鼠标事件这样的事情,但是当有大量对象时,它会显着减慢

那些SVG DOM引用意味着处理你绘制的东西的一些步骤是为你完成的。 渲染真正的大对象时SVG速度更快,但渲染许多对象时速度更慢。

Canvas中的游戏可能会更快。 一个巨大的地图程序在SVG中可能会更快。 如果你想使用Canvas,我有一些关于获取可移动对象的教程。

canvas对于更快速的事情和繁重的位图操作(比如animation)会更好,但是如果你想要很多的交互性,将需要更多的代码。

我已经在HTML DIV制作的绘图和Canvas制作的绘图上运行了一堆数字。 我可以写一个关于每个好处的巨大的post,但我会给我的testing的一些相关的结果考虑你的具体应用:

我做了Canvas和HTML DIVtesting页面,都有可移动的“节点”。 canvas节点是我创build的对象,并在Javascript中保持跟踪。 HTML节点是可移动的Div。

我为每个testing添加了100,000个节点。 他们的performance完全不同:

HTMLtesting选项卡永久加载(定时稍微在5分钟以下,第一次请求刷新页面)。 Chrome的任务pipe理器说该标签占用了168MB。 当我看的时候,占用12-13%的CPU时间,当我不看的时候占用0%。

“canvas”选项卡在一秒钟内加载,占用30MB。 无论是否正在查看,它总是占用CPU时间的13%。 (2013年编辑:他们主要是固定的)

因为当前的设置是在Canvastesting中每30毫秒重新绘制一次,所以在HTML页面上拖动更加平滑,这是devise期望的。 Canvas对此有很多优化。 (帆布失效是最简单的,还裁剪区域,有select性的重绘,等等。只是取决于你有多less感觉实施)

毫无疑问,你可以让Canvas在对象操作上更快,就像在这个简单的testing中的div一样,当然,加载时间也会更快。 Canvas中的绘图/加载速度更快,而且还有更多的优化空间(也就是说,排除非屏幕的东西非常容易)。

结论:

  • SVG对于应用程序和应用程序而言可能更好(less于1000个?实际取决于)
  • canvas对于成千上万的对象和小心的操作来说更好,但是需要更多的代码(或者库)才能实现。
  • HTML Div是笨重的,不能缩放,只有圆angular可能会使圆形成为可能,但复杂的形状是可能的,但涉及数以百计的微小像素宽度的div。 疯狂随之而来。

为了补充这一点,我一直在做一个图表应用程序,最初是用canvas开始的。 该图由许多节点组成,并且可以变得相当大。 用户可以拖动图中的元素。

我发现在我的Mac上,对于非常大的图像,SVG是优越的。 我有一个MacBook Pro 2013 13“视网膜,它运行在下面的小提琴相当好,图像是6000×6000像素,有1000个对象,当用户在物体周围拖动物体时,类似的canvas构造是不可能的。图。

在现代显示器上,你也必须考虑到不同的分辨率,在这里SVG给你所有这些免费的。

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

全屏: 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 100 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); 

我同意Simon Sarris的结论:

我将Protovis(SVG)中的一些可视化与处理js(Canvas)进行了比较,显示了> 2000个点,处理j比原型快得多。

使用SVG处理事件当然是非常重要的,因为您可以将它们附加到对象上。 在canvas中,您必须手动(检查鼠标位置等),但对于简单的交互,它不应该很难。

还有dojo工具包的dojo.gfx库。 它提供了一个抽象层,您可以指定渲染器(SVG,Canvas,Silverlight)。 这可能也是一个可行的select,虽然我不知道额外的抽象层增加了多less开销,但它使得编码交互和animation变得容易,并且是渲染器不可知的。

这里有一些有趣的基准:

出于您的目的,我build议使用SVG,因为您可以获得DOM事件,例如包括拖放在内的鼠标处理,您不必实现自己的重绘,而且您不必跟踪你的对象。 当你需要做位图image processing时使用Canvas,当你想操纵HTML中创build的东西时使用常规的div。 至于性能,你会发现现代浏览器现在正在加速所有这三个,但这个canvas已经得到了迄今最受关注。 另一方面,如何编写您的JavaScript是至关重要的,以获得最好的性能与canvas,所以我仍然build议使用SVG。

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

帆布

  • 分辨率依赖
  • 不支持事件处理程序
  • 糟糕的文字渲染function
  • 您可以将生成的图像保存为.png或.jpg
  • 非常适合graphics密集型游戏

SVG

  • 分辨率无关
  • 支持事件处理程序
  • 最适合具有大型渲染区域的应用程序(Google地图)
  • 缓慢的渲染如果复杂(任何使用DOM的东西都会很慢)
  • 不适合游戏应用程序

只是我的2分钱关于divs选项。

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

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