动态创建元素并能够移动它们的最佳方法是什么?例如,假设我想创建一个矩形、圆和多边形,然后选择这些对象并移动它们。
我知道HTML5提供了三个元素,可以使这成为可能:svg, canvas和div。对于我想做的事情,这些元素中哪一个将提供最佳性能?
为了比较这些方法,我想创建三个视觉上相同的网页,每个网页都有一个页眉、页脚、小部件和文本内容。第一个页面中的小部件将完全使用canvas元素创建,第二个页面完全使用svg元素创建,第三个页面使用普通div元素、HTML和CSS创建。
动态创建元素并能够移动它们的最佳方法是什么?例如,假设我想创建一个矩形、圆和多边形,然后选择这些对象并移动它们。
我知道HTML5提供了三个元素,可以使这成为可能:svg, canvas和div。对于我想做的事情,这些元素中哪一个将提供最佳性能?
为了比较这些方法,我想创建三个视觉上相同的网页,每个网页都有一个页眉、页脚、小部件和文本内容。第一个页面中的小部件将完全使用canvas元素创建,第二个页面完全使用svg元素创建,第三个页面使用普通div元素、HTML和CSS创建。
当前回答
它们都有好的方面和坏的方面,下面我们来比较一下。
Canvas将具有最佳的整体性能,但前提是您正确使用它。
Divs:
良好的性能 您可以使用DOM操作它 您可以访问DOM事件 CSS支持 很难做出复杂的形状
性能测试:https://kajam.hg0428.repl.co/pref/
帆布:
更好的形状支撑 伟大的成就 强大的浏览器支持 没有CSS
性能测试:https://js-game-engine.hg0428.repl.co/canvasTest/preform.html
svg:
更好的形状支撑 更难使用 良好的浏览器支持 没有CSS,但有很多不同的SVG 糟糕的性能
我还没有对此进行性能测试,但根据其他测试,它并不好。
要使Canvas快速:
Canvas可以具有非常动态的性能,因此让我们回顾一些技巧。 避免使用ctx。Rect和ctx。填充,使用ctx。fillRect代替,这是最大的一个,它可以毁掉即使是最简单的游戏。 不要使用填充和描边的形状,而是使用填充[形状]。
如果你不记得在使用canvas时,你的游戏将会非常慢。这是我从经验中学到的。
其他回答
为了补充这一点,我一直在做一个图表应用程序,最初是从画布开始的。该图由许多节点组成,而且它们可以变得相当大。用户可以在图中拖动元素。
我发现,在我的Mac上,对于非常大的图像,SVG更好。我有一台MacBook Pro 2013 13英寸Retina,它在下面的操作非常好。图像是6000x6000像素,有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 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);
了解SVG和Canvas之间的区别将有助于选择正确的格式。
帆布
分辨率的依赖 不支持事件处理程序 糟糕的文本渲染能力 您可以将生成的图像保存为.png或.jpg 非常适合图像密集型游戏
SVG
分辨率独立 支持事件处理程序 最适合具有大渲染区域的应用程序(谷歌Maps) 如果复杂,呈现速度会很慢(任何大量使用DOM的东西都会如此) 慢) 不适合游戏应用
我同意Simon Sarris的结论:
我比较了Protovis (SVG)和Processingjs (Canvas)中的一些可视化,后者显示> 2000点,Processingjs比Protovis快得多。
使用SVG处理事件当然要容易得多,因为您可以将它们附加到对象上。在Canvas中,你必须手动操作(检查鼠标位置等),但对于简单的交互来说,这应该不难。
还有道场。dojo工具包的GFX库。它提供了一个抽象层,你可以指定渲染器(SVG、Canvas、Silverlight)。这可能也是一个可行的选择,尽管我不知道额外的抽象层增加了多少开销,但它使编码交互和动画变得容易,并且与渲染器无关。
以下是一些有趣的基准测试:
http://svbreakaway.info/tp.php#jan21a http://www.eleqtriq.com/2010/02/canvas-svg-flash/ http://smus.com/canvas-vs-svg-performance/
简单的回答是:
SVG对您来说更简单,因为已经内置了选择和移动它。SVG对象是DOM对象,因此它们有“点击”处理程序等。
div还可以,但是笨重,在大量加载时性能很差。
Canvas无疑具有最好的性能,但是您必须自己实现托管状态的所有概念(对象选择等),或者使用库。
长话短说:
HTML5 Canvas只是一个位图的绘制表面。你设置了绘制(比如用颜色和线条粗细),绘制了那个东西,然后Canvas没有那个东西的知识:它不知道它在哪里,也不知道你刚刚画的是什么,它只是像素。如果你想要绘制矩形并让它们四处移动或可选择,那么你必须从头开始编写所有这些代码,包括记住你画了它们的代码。
另一方面,SVG必须维护对其呈现的每个对象的引用。您创建的每个SVG/VML元素都是DOM中的真实元素。默认情况下,这允许您更好地跟踪您创建的元素,并使处理鼠标事件等事情更容易默认,但当有大量对象时,它会显着变慢
这些SVG DOM引用意味着一些处理所绘制事物的步法已经为您完成了。SVG在呈现非常大的对象时速度更快,但在呈现许多对象时速度较慢。
在Canvas中游戏可能会更快。大型地图程序使用SVG可能会更快。如果你确实想使用Canvas,我有一些教程,让可移动的对象在这里运行。
Canvas更适合于快速的内容和重位图操作(如动画),但如果你想要大量的交互性,则需要更多的代码。
我在HTML div制作的绘图和canvas制作的绘图上运行了一堆数字。我可以写一篇关于每种方法的好处的文章,但我将给出一些相关的测试结果,以供您考虑特定的应用程序:
我制作了Canvas和HTML DIV测试页面,两者都有可移动的“节点”。Canvas节点是我在Javascript中创建并跟踪的对象。HTML节点是可移动的div。
我在两个测试中分别添加了100,000个节点。他们的表现完全不同:
HTML测试标签永远加载(时间略低于5分钟,chrome要求第一次杀死页面)。Chrome的任务管理器说这个选项卡占用了168MB。当我看着它时,它会占用12-13%的CPU时间,当我不看着它时,它会占用0%的CPU时间。
Canvas标签在一秒内加载,占用30MB。它还会一直占用13%的CPU时间,无论你是否在看它。(2013年编辑:他们基本上已经解决了这个问题)
在HTML页面上拖动更流畅,这是设计所期望的,因为当前的设置是在Canvas测试中每30毫秒重绘EVERYTHING。为此,Canvas有很多优化。(画布失效是最简单的,还有剪切区域,选择性重绘等。这取决于你有多喜欢执行)
毫无疑问,在这个简单的测试中,你可以让Canvas在对象操作上更快,当然在加载时间上也更快。在Canvas中绘制/加载更快,也有更多的优化空间(也就是说,排除屏幕外的东西是非常容易的)。
结论:
SVG可能更适合应用程序和项目较少的应用程序(少于1000个?取决于真的) Canvas更适合成千上万的对象和仔细的操作,但需要更多的代码(或库)才能使它起步。 HTML div是笨拙的,不能缩放,制作一个圆只能用圆角,制作复杂的形状是可能的,但涉及到数百个极小的像素宽的div。疯狂。
只是我对divs选项的意见。
《Famous/Infamous》和《samyazare》(可能还有其他游戏)使用绝对定位的非嵌套divs(带有非繁琐的HTML/CSS内容),结合matrix2d/matrix3d进行定位和2D/3D转换,并在中等移动硬件上实现了稳定的60FPS,所以我不认为divs是一个缓慢的选择。
Youtube和其他地方有大量的屏幕记录,高性能的2D/3D东西运行在浏览器中,所有东西都是一个DOM元素,你可以在上面检查元素,60FPS(混合WebGL用于某些效果,但不适用于渲染的主要部分)。