我们在网络应用上使用了d3.layout.force
,我一直在调查一个在Android上运行缓慢的错误报告:与在桌面上的工作方式相比,它感觉就像节点在油中浏览器或iOS。
(顺便说一句,我们只有4到9个节点,4到9之间的迟缓感觉不同。)
我们设置size()
,linkDistance()
和charge()
;所以我们使用摩擦,θ,alpha,重力等的默认值。我尝试使用这些来尝试在桌面上重现效果,但不能。 (friction(0.67)
,而不是默认值0.9,是最接近的,但仍然感觉不同,不知何故。)
然后我设置了一个FPS表(基于对tick()
功能的调用)。我们在台式机上获得60fps,而在ipad上似乎是40s和50s。但是在Android Chrome上(在Nexus 7上)它似乎上限为30fps,而且往往只有一半。 Android Firefox通常在20多岁,但有时会进入30年代。
那么,一个合理的假设是Android设备只是慢一点吗? Android Chrome可能会有30fps的上限吗?
然后我该如何解决这个问题?我相信d3.js使用requestAnimationFrame()
。通常,动画库会在调用requestAnimationFrame()
之间花费时间来决定移动对象的距离(因此当CPU过载时,动画会变得更加笨拙,但需要相同的时间才能完成)。但似乎d3.js不会这样做,并且通过刻度而不是经过的时间将所有内容移动相同的数量。我该怎么办?
(理想情况下,我想要一个基于机器速度慢/快的解决方案,而不是必须嗅探浏览器。)
答案 0 :(得分:0)
奇怪的是,在我自己的force.tick()
处理程序中添加了对requestAnimationFrame()
的更多调用(请参阅https://stackoverflow.com/a/26189110/841830), 会增加FPS。这表明它不受CPU限制,而是Android强制执行的限制(可能是为了节省电池?)。
这是我正在使用的代码,它试图动态适应当前的fps;它不漂亮,但似乎是在我的测试Android设备上完成工作,而不改变iOS或桌面的行为。
首先,在哪里设置force
布局:
var ticksPerRender = 0;
var animStartTime,animFrameCount;
force.on('start',function start(){
animStartTime = new Date();animFrameCount=0;
});
requestAnimationFrame(function render() {
for(var i = 0;i < ticksPerRender;i++)force.tick();
if(force.alpha() > 0)requestAnimationFrame(render);
});
以上做了两件事:
ticksPerRender
从零开始)。然后在tick
处理程序的末尾:
++animFrameCount;
if(animFrameCount>=15){ //Wait for 15, to get an accurate count
var now = new Date();
var fps = (animFrameCount / (now - animStartTime))*1000;
if(fps < 30){
ticksPerRender++;
animStartTime = now;animFrameCount = 0; //Reset the fps counter
}
if(fps > 60 && ticksPerRender >= 1){
ticksPerRender--;
animStartTime = now;animFrameCount = 0; //Reset the fps counter
}
}
这表示如果FPS较低(低于30),请在每个动画帧上额外调用tick()
。如果它变高(超过60),请删除额外的呼叫。
每次更改ticksPerRender时,我们都会从头开始测量FPS。