使用javascript实现高效的SVG实体实时管理

使用javascript实现高效的SVG实体实时管理,javascript,memory-management,svg,Javascript,Memory Management,Svg,[编辑]叹气。。。这里的“垃圾邮件保护”不允许我发布链接,所以我想应该是URI [edit2]好的,可以通过regexp的URI的断开形式…[/edit2] 首先,我要说我对SVG完全陌生,对Javascript也有点陌生,我来自低级C语言的背景。不过,我一时兴起,决定尝试使用所有这些有趣的新web技术编写一个实时游戏 我完全准备好回答“对不起,网络还不能做到这一点!”对于浏览器来说,这可能只是太多的数据吞吐量 所以我写了小行星克隆的开始。这是一个很薄的SVG文档,整个游戏由javascript

[编辑]叹气。。。这里的“垃圾邮件保护”不允许我发布链接,所以我想应该是URI [edit2]好的,可以通过regexp的URI的断开形式…[/edit2]

首先,我要说我对SVG完全陌生,对Javascript也有点陌生,我来自低级C语言的背景。不过,我一时兴起,决定尝试使用所有这些有趣的新web技术编写一个实时游戏

我完全准备好回答“对不起,网络还不能做到这一点!”对于浏览器来说,这可能只是太多的数据吞吐量

所以我写了小行星克隆的开始。这是一个很薄的SVG文档,整个游戏由javascript动态生成为SVG线条/多边形实体。令我大吃一惊的是,这确实奏效了。我能够从Firefox3.5中获得大部分平滑的动画(没有在任何其他软件上测试)

  • (javascript)http-public.codenazi.fastmail.fm/asteroids_dynamic.js
每次撞击岩石时,都会发生这种变化:

// on startup
svg_ns = 'http://www.w3.org/2000/svg';
container = svgdoc.getElementById('rocks');

// each time a rock breaks, times ~20
x = svgdoc.createElementNS(svg_ns, "polygon");
x.setAttribute(...various things...);
container.appendChild(x);
不幸的是,它不够平滑。它总是滞后。即使在我的现代3GHz机顶盒上,流量也会出现抖动和中断。我给几个朋友看了,他们也立即抱怨口吃

我花了大约一周的时间阅读了如何优化javascript,这有点帮助,但我怀疑问题在于我在游戏中几乎每一个动作中对DOM进行的所有插入/删除。我已经考虑过各种预分配方案,如果它实际上没有帮助的话,我真的不想要一些复杂的内存管理器

在我的研究中,有很多关于“回流”和“重涂”的讨论。据我所知,对DOM的任何插入/删除都会导致对整个树进行某种形式的重新解析,这很慢。常见的解决方案是先收集子节点,然后只在实际文档中插入一个。不过,这种模式在这样的游戏中并不适用

作为测试,我将这两个想法结合起来:可能的话预先分配,可能的话分组插入。因此,在这个版本中,每个小行星都会被SVG组替换,小行星、它的爆炸效果和它的弹出分数都会同时创建。这样,分配和插入只有在小行星被创建(而不是被摧毁)时才会发生。为了在需要之前隐藏这些额外效果,我设置了“display:hidden”属性

  • 新的组预分配版本:http-public.codenazi.fastmail.fm/asteroids\u prealloc.svg
  • (javascript):http-public.codenazi.fastmail.fm/asteroids_prealloc.js
创建岩石时,会发生以下情况:

g = svgdoc.createElementNS(svg_ns, "g");
// make the rock itself
rock = svgdoc.createElementNS(svg_ns, "polygon");
rock.setAttribute(...various things...);
g.appendChild(rock);
// make the destroy effect (repeated many times)
frag = svgdoc.createElementNS(svg_ns, "line");
frag.setAttribute(...various things...);
frag.style.display = 'none';
g.appendChild(frag);
// actually add it
container.appendChild(g);

// then, sometime later when a hit is detected
rock.style.display = 'none';
frag.style.display = 'block';
我想这确实让它变得更平滑了!但是它还显著降低了帧率。我必须一次跟踪更多的元素,一些测试表明,将所有内容包装到另一个元素中也会使SVG渲染速度变慢

所以我的问题是:这可能吗?我真的可以从firefox中获得这样一个相当平滑的SVG动画吗?还是firefox天生就会出现停顿/口吃?如果可能的话,是否有一些内存/元素管理技术可以以比我目前更好的方式分配/插入SVG元素


我有点怀疑答案将是坚持使用第一种更简单的方法,使用更少的元素,等待浏览器更好的未来-唉——

我还没有尝试SVG动画(还没有);但Canvas却出人意料地擅长于此;尤其是当你做图层的时候

简而言之,为每个层创建画布对象,并分别擦除/重画每个层。您还可以在屏幕外画布和显示的画布之间快速切换


我知道,理论上SVG应该快得多;但正如您所注意到的,DOM解析会杀死您。有了Canvas,就没有这个必要了。

好的,首先要做的是:

伙计-这是我见过的最棒的SVG。谢谢分享


它在我的系统上运行得非常顺利,直到我一下子摧毁了一堆石头。如果用预先制作的SVG动画替换动态frag动画会怎么样?这会提高性能吗?

这是个好主意。我不确定它是否会加速,但它是完全值得尝试的。我怀疑这是正确的解决方案,但现在我要考虑使用画布放弃。这其中一半是为了尝试精简SVG,所以canvas有点达不到目的。Waaaaay很晚才更新,但我有意识地使用canvas重新实现了整个游戏,而且它的效果比您所说的要好得多。平滑度的差异是惊人的。我想我得等SVG赶上了。。。