平滑地动画属性改变到3000个拉斐尔对象一次

Smoothly animate attribute changes to ~3000 Raphael objects at once

本文关键字:对象 一次 动画 属性 改变 3000个 平滑      更新时间:2023-09-26

更新问题我已经更新了这一点更简洁…:

在这个小提琴:http://jsfiddle.net/pX2Xb/4/我有一些拉斐尔代码,画3000个圆圈到一个页面。然后,它试图在10秒内一次动画所有的圆圈(改变填充颜色),这导致了一个笨拙的视觉动画。将圆圈的数量更改为20,以看到更流畅的动画进行比较。

我的问题是(a)是否有可能让我更新到3000个元素更流畅和(b)如果是这样,代码是什么样子的?

一些注意事项:

  • 我愿意接受一个小的时间打击,如果有一些方法来优化这一点,但是,例如,我希望所有圈至少在1.5倍更新,无论动画时间设置为。所以,如果动画是10秒,那么所有的圆圈应该在15秒内改变。
  • 3000个元素是目前我的限制,所以我很高兴它的工作:)在说,如果一个解决方案可以有效地处理比这更多,对于一般情况下,那将是非常伟大的。

旧的细节,如果它有帮助的话

我正在创建一个美国县的大地图,其中有3000多个;我使用这个Wikipedia svg文件来获取相关的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明智(可能是一个大问题)。

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

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

谢谢,oli

我不知道为什么,但是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/

因为我目前不熟悉Rapael.js,我只是建议,在一个通用的JavaScript方式,你可以创建一个changeRaphaelPathAttributeEvent,你会发出每次你想改变路径,属性的变化作为参数说的事件。然后,如果可能的话,将事件处理程序附加到执行属性更改的每个路径上。

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

注意:这只是一个解决方案,以避免直接的性能影响。也许有其他的解决方案可以最小化需要访问的对象的数量,你也应该考虑(我不能告诉你,因为我不太了解拉斐尔)。

所有的路径都是手工写的吗?我认为把所有路径放到一个对象中会更好。然后你可以迭代对象并使用for in绘制所有路径。在这个过程中,您可以使用element.id = 'name'为每个路径提供一个内部ID。一旦你有了所有的内部ID和路径绘制,你可以使用getById方法:getById('pathId')如果你要使用set,我建议你使用cloclosure,你可以首先声明变量

var setName = Paper.Set()

,然后将路径推入另一个循环

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

然后你有Paper.forEach()这样的方法,如果你想应用一些属性的元素。或者Set.FotEach()。两者都接受一个回调函数,如参数,然后在每次迭代中执行该函数。

如果你想分享你的代码,对我来说检查它并给出我对如何解决一些情况的意见并不是一个问题。我也在研究地图,我正在开发一款教育电子游戏,如果你愿意,我也可以与你分享我的代码,关于拉斐尔的文档并不多,所以对我来说,看看你是如何使用它的会很有用,也许对你来说也是一样的。

再见!

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

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

下面是一个例子:http://jsfiddle.net/dqJps/25/