2015-10-29 4 views
1

Мы используем d3.layout.force в веб-приложении, и я изучаю отчет об ошибке, который вялый на Android: он чувствует, что узлы находятся в масле, по сравнению с тем, как это работает на настольных браузерах или iOS.Как избежать вялой схемы размещения d3 на Android?

(Кстати, мы только когда-либо между 4 и 9 узлов, и вялость не чувствует себя отличается от 4 и 9.)

Мы установили size(), linkDistance() и charge(); поэтому мы используем значения по умолчанию для трения, тета, альфа, гравитации и т. д. Я экспериментировал с ними, чтобы попытаться воспроизвести эффект на рабочем столе, но не смог. (friction(0.67), а не по умолчанию 0,9, был самым близким, но все равно чувствовал себя как-то иначе).

Затем я установил счетчик FPS (на основе вызовов функции tick()). Мы получаем 60 кадров в секунду на рабочем столе, и это похоже на 40-е и 50-е годы на ipad. Но на Android Chrome (на Nexus 7) он кажется закрытым со скоростью 30 кадров в секунду, и часто это вдвое меньше. Android Firefox был в 20-х годах, но иногда в 30-е.

Итак, разумная ли гипотеза, что устройства Android работают медленнее? Может ли быть кепка 30 кадров в секунду в Android Chrome?

Тогда как я могу это исправить? Я считаю, что d3.js использует requestAnimationFrame(). Часто библиотеки анимации занимают время между вызовами до requestAnimationFrame(), чтобы решить, как далеко перемещать объекты (поэтому, когда процессор перегружается, анимация становится более резкой, но требует того же времени). Но похоже, что d3.js этого не делает и перемещает все одинаковое количество по тику, а не по истекшему времени. Что я могу сделать по этому поводу?

(В идеале я хотел бы решение, основанное на том, как быстро/медленно машина, вместо того, чтобы нюхать браузер.)

+0

[Этот вопрос] (https://stackoverflow.com/questions/18311818/speed-up-d3-force-layout-with-many-nodes-and-links) и [этот вопрос] (https: // stackoverflow.com/questions/26188266/how-to-speed-up-the-force-layout-animation-in-d3-js) может помочь. –

+0

@LarsKotthoff Спасибо. У меня только несколько узлов (только что обновил вопрос). Я попробую идею в первой ссылке об использовании 'requestAnimationFrame()', чтобы добавить больше вызовов к 'tick()' ... если я связан с ЦП из-за времени, проведенного в 'tick()', я предполагаю это не будет иметь никакого значения; так что будет интересно посмотреть, что произойдет. –

ответ

0

Любопытно, добавив больше звонков в force.tick() в моем собственном requestAnimationFrame() обработчиком (см https://stackoverflow.com/a/26189110/841830), делает увеличить FPS. Это говорит о том, что он не связан с ЦП, а вместо этого лимит, который поддерживает 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); 
    }); 

выше делает две вещи:

  1. устанавливает ФПС счетчик
  2. устанавливает нашей собственной анимации обратного вызова, который делает ничего по умолчанию (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 с нуля.

 Смежные вопросы

  • Нет связанных вопросов^_^