即时创建元素并能够移动元素的最佳方法是什么?例如,假设我要创建一个矩形,圆形和多边形,然后选择这些对象并四处移动。
我了解HTML5提供了三个使之成为可能的元素:svg,canvas和div。对于我想做什么,这些元素中的哪一个将提供最佳性能?
为了比较这些方法,我正在考虑创建三个视觉上相同的网页,每个网页中都有页眉,页脚,小部件和文本内容。第一页中的小部件将完全使用canvas
元素创建,第二页中的完全使用svg
元素创建,而第三页中的使用简单div
元素HTML和CSS创建。
即时创建元素并能够移动元素的最佳方法是什么?例如,假设我要创建一个矩形,圆形和多边形,然后选择这些对象并四处移动。
我了解HTML5提供了三个使之成为可能的元素:svg,canvas和div。对于我想做什么,这些元素中的哪一个将提供最佳性能?
为了比较这些方法,我正在考虑创建三个视觉上相同的网页,每个网页中都有页眉,页脚,小部件和文本内容。第一页中的小部件将完全使用canvas
元素创建,第二页中的完全使用svg
元素创建,而第三页中的使用简单div
元素HTML和CSS创建。
Answers:
SVG 对您来说会更容易,因为已经内置了选择和移动它的功能。SVG对象是DOM对象,因此它们具有“ click”处理程序等。
资料核实是不错,但笨重,具有可怕的大量性能负载。
Canvas具有最佳的性能,但是您必须自己实现托管状态(对象选择等)的所有概念,或者使用库。
HTML5 Canvas只是位图的绘图表面。您设置进行绘制(用颜色和线条粗细说),绘制该东西,然后Canvas不知道该东西:它不知道它在哪里或刚刚绘制的是什么,它是只是像素。如果要绘制矩形并使其移动或可以选择,则必须从头开始编写所有代码,包括要记住已绘制矩形的代码。
另一方面,SVG必须维护对其呈现的每个对象的引用。您创建的每个SVG / VML元素都是DOM中的真实元素。默认情况下,这使您可以更好地跟踪所创建的元素,并默认情况下使处理鼠标事件之类的事情变得更容易,但是当存在大量对象时,它会显着降低速度
这些SVG DOM参考意味着处理您绘制的事物的一些步法工作已为您完成。渲染非常大的对象时,SVG更快,但是渲染许多对象时,SVG则更慢。
在Canvas中,游戏可能会更快。大型地图程序在SVG中可能会更快。如果你想用画布,我对获得可移动物体和运行一些教程在这里。
对于更快的事物和繁重的位图操作(例如动画),Canvas会更好,但是如果您需要大量的交互性,Canvas将需要更多的代码。
我在用HTML DIV绘制的图形和通过Canvas绘制的图形上运行了大量数字。我可以就每种产品的优势发表大量文章,但我将给出一些测试相关结果,以供您针对特定应用进行考虑:
我制作了Canvas和HTML DIV测试页,它们都有可移动的“节点”。画布节点是我创建的对象,并使用Javascript进行跟踪。HTML节点是可移动的Div。
我向两个测试的每一个添加了100,000个节点。他们的表现截然不同:
HTML测试标签花费了很多时间(时间略少于5分钟,chrome要求第一次杀死该页面)。Chrome的任务管理器说该标签占用了168MB。当我查看时,它占用12-13%的CPU时间,当我不查看时,它占用0%的CPU时间。
“画布”选项卡在一秒钟内加载,占用30MB。不管是否有人看,它一直都在占用CPU时间的13%。(2013编辑:他们基本上已经解决了这个问题)
在HTML页面上的拖动更加平滑,这是设计所期望的,因为当前的设置是在Canvas测试中每30毫秒重绘所有内容。为此,Canvas有很多优化。(画布无效是最容易的,还有裁剪区域,选择性重绘等。这仅取决于您想要实现的程度)
毫无疑问,在该简单测试中,您可以使Canvas在对象操作上像divs更快,并且在加载时间上当然要快得多。在Canvas中,绘制/加载速度更快,并且还有更多的优化空间(即,排除屏幕外的内容非常容易)。
background-image
...尽管您可以在SVG /画布中做类似的事情
除此之外,我一直在做一个图表应用程序,最初是从画布开始的。该图包含许多节点,它们可能会变得很大。用户可以拖动图中的元素。
我发现在Mac上,对于非常大的图像,SVG更为出色。我有一台MacBook Pro 2013 13“ Retina,它在下面的小提琴中运行得很好。图像为6000x6000像素,有1000个对象。当用户在屏幕上拖动对象时,无法在画布上进行类似动画制作图。
在现代显示器上,您还必须考虑不同的分辨率,在这里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之间的差异将有助于选择正确的产品。
帆布
SVG
我同意Simon Sarris的结论:
我将Protovis(SVG)中的某些可视化与Processingjs(Canvas)进行了比较,后者显示> 2000点,并且processingjs比protovis快得多。
使用SVG处理事件当然要容易得多,因为您可以将事件附加到对象上。在“画布”中,您必须手动进行操作(检查鼠标位置等),但是对于简单的交互而言,这并不难。
还有dojo工具箱的dojo.gfx库。它提供了一个抽象层,您可以指定渲染器(SVG,Canvas,Silverlight)。尽管我不知道额外的抽象层会增加多少开销,但这可能也是一个可行的选择,但是它使交互和动画的编码变得容易,并且与渲染器无关。
以下是一些有趣的基准:
尽管上面的大多数答案仍然有些道理,但我认为它们值得更新:
多年来,SVG的性能有了很大的提高,现在,针对SVG的硬件加速CSS过渡和动画完全不依赖于JavaScript性能。当然,JavaScript的性能也得到了改善,并且Canvas的性能也得到了改善,但并没有SVG得到改善。另外,现在几乎所有浏览器中都提供了一个“新手”,那就是WebGL。使用与Simon相同的词语:它击败了Canvas和SVG。但是,这并不意味着它应该成为首选技术,因为它是一种野兽,并且只能在非常特定的用例中更快。
在当今大多数用例中,恕我直言,SVG提供了最佳的性能/可用性比。可视化必须非常复杂(就元素数量而言),同时又必须非常简单(每个元素),以便Canvas甚至更多,WebGL才能真正发挥作用。
layers.acceleration.force-enabled
在Firefox中与视频解码无关。这是众所周知的事实。完成循环时,使用requestAnimationFrame是另一个级别,从而可以进行更多重绘。与视频完全无关。
出于您的目的,我建议您使用SVG,因为您会获得DOM事件,例如包含鼠标操作(包括拖放)在内的DOM事件,因此您不必实现自己的重绘,也不必跟踪状态。你的对象。当您需要进行位图图像处理时,请使用Canvas;而当您要处理用HTML创建的内容时,请使用常规div。关于性能,您会发现现代浏览器现在正在加速这三种浏览器,但是到目前为止,canvas是最受关注的。另一方面,JavaScript编写的好坏对于使画布发挥最大性能至关重要,因此我仍然建议您使用SVG。
在谷歌搜索时,我在http://teropa.info/blog/2016/12/12/graphics-in-angular-2.html中找到了有关SVG和Canvas的使用和压缩的很好的解释。
希望能帮助到你:
- 像HTML一样,SVG使用保留的呈现方式:当我们想在屏幕上绘制矩形时,我们在DOM中声明性地使用一个元素。然后,浏览器将绘制一个矩形,但它还将创建一个表示该矩形的内存中SVGRectElement对象。这个对象是我们需要操纵的东西–它被保留了。我们可以随时间分配不同的位置和大小。我们还可以附加事件侦听器以使其具有交互性。
- Canvas使用立即渲染:当我们绘制一个矩形时,浏览器会立即在屏幕上渲染一个矩形,但是永远不会有任何代表它的“矩形对象”。画布缓冲区中只有一堆像素。我们不能移动矩形。我们只能绘制另一个矩形。我们无法响应矩形上的点击或其他事件。我们只能响应整个画布上的事件。
因此,canvas是比SVG更底层的限制性API。但这有一个缺点,那就是使用画布您可以用相同的资源量执行更多操作。因为浏览器不必创建和维护我们绘制的所有对象的内存对象图,所以它需要更少的内存和计算资源即可绘制相同的视觉场景。如果您要绘制非常大而复杂的可视化效果,则Canvas可能是您的理想选择。