平滑动画属性一次更改为~3000 Raphael对象

时间:2011-11-23 08:41:13

标签: javascript svg visualization raphael

更新的问题 我已将此更新为更简洁..:

在这个小提琴中:http://jsfiddle.net/pX2Xb/4/我有一些raphael代码可以在页面上绘制3000个圆圈。然后,它会尝试在10秒内一次动画所有圆圈(更改填充颜色),这会产生笨重的视觉动画。将圆圈数更改为20以查看更平滑的动画以进行比较。

我的问题是(a)我是否可以更顺利地更新3000个元素;(b)如果是这样,那么代码看起来是什么样的?

一些注意事项:

  • 我愿意采取一些小的时间点,如果有一些方法来优化这个,但是,例如,我希望所有圈至少已经更新了1.5倍无论动画时间设置为。因此,如果动画为10秒,则所有圆圈都应在15中更改。
  • 目前3000个元素大致是我的限制,所以我很乐意为它工作:)在说,如果一个解决方案可以有效地处理更多,对于一般情况,这是真的大。

较旧的详情,如果有帮助

我正在制作一张美国郡的大地图,其中有超过3000个;我正在使用this Wikipedia svg file获取相关的SVG路径来创建地图,并使用RaphaelJs渲染地图。

因此,我最终得到了超过3000条类似于以下内容的陈述:

    var cc_02130 = rsr.path("M 140.66674,.... 320.11635"); // county path
    cc_02130.attr({id: '02130',.. .."marker-start": 'none'}); // init attrs

我还创建了一个Paper.set()对象来保存所有这些元素:

var myset = paper.set([cc_56039, cc_56040, cc_56041 ...])

暂时忘记这里实际生成的文件非常大,我非常感谢如何对上面详述的对象卷进行更改的建议,这既快又合理,但是CPU明智的< / em>(可能是一个很大的问题)。

我绝对愿意改变我的代码/对象的结构,只要我可以单独更改特定县的属性。  例如,我希望能够在一两秒内为所有路径内容应用不同的颜色(对于所有3000 +)。

我面临的挑战不是如何应用颜色变化,动画等,而是如何快速有效地完成这项工作。现在,如果我循环并对3000多个对象进行更改,我的机器会对我尖叫;作为一种替代方案,我使用setTimeout将更改分解为更小的块(可能一次10个,延迟40毫秒)。超过3000项,这变得非常慢,仍然使用大量的CPU。

谢谢, OLI

4 个答案:

答案 0 :(得分:10)

我不知道为什么,但D3.js在一次动画大量元素时效率更高。您可以通过创建一个Raphael函数使它们无缝地工作,该函数接收一个集合并返回您想要设置动画的html对象:

Raphael.st.nodes = function() {
  var elements = [];
  this.forEach(function (i) {
     elements.push(i.node);
  });
  return elements;
}

然后你让d3从那里拿走它

//circleholder is a Raphael set
elements = circleholder.nodes()
d3.selectAll(elements)
  .transition()
  .attr("fill", function(d,i){return colours[randomNum(14)]})
  .duration(ANIMATION_DELAY)

这是jsfiddle:http://jsfiddle.net/mFecs/

答案 1 :(得分:0)

由于我目前不熟悉Rapael.js,我只是建议您以通用的JavaScript方式创建一个changeRaphaelPathAttributeEvent,每当您想要更改路径,属性更改为所述事件的参数。然后将事件处理程序附加到执行属性更改的每个路径(如果可能的话)。

这样,您就可以解决循环访问所有路径变量并同步更改属性的问题(这会直接影响页面在处理时的响应性);该方法对用户体验的性能影响较小。

注意:这只是解决即时性能问题的解决方案。也许有其他解决方案可以最大限度地减少访问所需的对象数量,你也应该考虑(而且我无法告诉你,因为我不太了解拉斐尔)。

答案 2 :(得分:0)

您是否手动编写了所有路径?如果你将所有路径都放在一个对象中,我认为会更好。然后,您可以使用例如for in迭代对象并绘制所有路径。在该过程中,您可以使用element.id = 'name'为每个路径提供内部ID。一旦你拥有了所有的内部ID和绘制的路径,就可以使用getById方法:getById('pathId')如果你打算使用集合,我建议你使用Clousures,你可以先声明变量

var setName = Paper.Set()

然后在另一个循环中推送路径

for (countie in Lousiana){
    setName.push(countie)
}

如果要将某些属性应用于元素,则可以使用Paper.forEach()之类的方法。或Set.FotEach()。两者都采用类似参数的回调函数,然后在每次迭代中执行该函数。

如果你想分享你的代码,那么对我来说检查它并就如何解决某些情况提出意见并不成问题。我也在使用地图,我正在开发一个教育视频游戏,如果你想我也可以与你分享我的代码,没有那么多关于Raphael的文档,所以对我来说看看它是如何有用的你使用它,也许对你来说也一样。

再见!

答案 3 :(得分:-1)

老实说,任何计算机都应该很容易更改3000个项目的属性。 Raphael对每个动画元素使用setInterval。更改元素的属性后,浏览器将重新绘制整个页面。这是2999次必要的重新抽奖。

以下是我要做的事情:使用循环来改变每个元素,而不是使用Raphael动画。它有点复杂,但速度更快。此外,您可以更改每秒的步数。如果动画运行速度太慢,只需减少每秒的步数。

以下是一个示例:http://jsfiddle.net/dqJps/25/

希望这有帮助。