Плавно анимированный атрибут меняется на ~ 3000 объектов Рафаэля за раз - PullRequest
5 голосов
/ 23 ноября 2011

ОБНОВЛЕННЫЙ ВОПРОС Я обновил это, чтобы быть немного более кратким ..:

В этой скрипке: http://jsfiddle.net/pX2Xb/4/ У меня есть некоторый код Рафаэля, который рисует 3000 круговна страницу.Затем он пытается анимировать все круги одновременно (меняет цвет заливки) в течение 10 секунд, что приводит к неуклюжей визуальной анимации.Измените количество кругов на 20, чтобы увидеть более плавную анимацию для сравнения.

Мои вопросы: (а) я могу сделать обновление 3000 элементов более плавным и (б) если да, то чтокод для этого выглядит?

Некоторые примечания:

  • Я готов нанести небольшой удар по времени, если есть какой-то способ оптимизировать это, но, например, я бы хотел all кругов, по крайней мере, обновляются в 1,5 раза независимо от времени анимации.Итак, если анимация длится 10 секунд, все круги должны были измениться за 15.
  • 3000 элементов - это примерно мой предел на данный момент, так что я был бы рад, если бы это работало на это :)решение может эффективно обрабатывать больше, чем это, для общего случая, это было бы действительно здорово.

более старые детали, в случае, если это помогает

Iсоздаю большую карту округов США, которых насчитывается более 3000;Я использую этот файл Википедии 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 ...])

На мгновение забыв, чтоФайл, сгенерированный на самом деле, здесь довольно большой, я был бы очень признателен за предложения , как я могу применить изменения к объему объектов, описанных выше, что является быстрым и достаточно разумным для процессора (возможно, большой вопрос).

Я определенно открыт для изменения структуры моего кода / объектов, если я могу индивидуально изменять атрибуты определенных округов.Например, я хотел бы иметь возможность применять разные цвета для каждого содержимого пути в секунду или две (для всех 3000+).

Проблема, с которой я сталкиваюсь, заключается не в том, как применить изменения цветаанимации и т. д., но как это сделать быстро и эффективно.Прямо сейчас моя машина кричит на меня, если я повторяю цикл и применяю изменения к более чем 3000 объектам;в качестве альтернативы я использовал setTimeout, чтобы разбить изменения на более мелкие фрагменты (возможно, 10 за раз, с задержкой 40 мс).Более 3000 предметов, это становится довольно медленным, и все еще использует много процессора.

Спасибо, oli

Ответы [ 4 ]

10 голосов
/ 04 января 2012

Не знаю почему, но 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/

0 голосов
/ 24 ноября 2011

Вы писали все пути вручную? Я думаю, что лучше, если вы положите все пути в объекте. Затем вы можете выполнить итерацию объекта и нарисовать все пути, используя, например, for in. В этом процессе вы можете присвоить внутренний идентификатор каждому пути, используя element.id = 'name'. Когда у вас есть все внутренние идентификаторы и нарисованные пути, вы можете использовать метод getById: getById('pathId') Если вы собираетесь использовать наборы, я рекомендую вам использовать Clousures, вы можете сначала объявить переменные

var setName = Paper.Set()

, а затем вставьте пути в другой цикл

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

Тогда у вас есть методы, такие как Paper.forEach(), если вы хотите применить некоторые атрибуты к элементам. Или Set.FotEach(). Оба принимают функцию обратного вызова как аргумент, а затем выполняют эту функцию в каждой итерации.

Если вы хотите поделиться своим кодом, для меня не составит труда проверить его и высказать свое мнение о том, как решить некоторые ситуации. Я также работаю с картами, я занимаюсь разработкой обучающей видеоигры. Если вы хотите, я также могу поделиться с вами своим кодом, документации о Рафаэле не так много, поэтому мне было бы полезно узнать, как Вы используете это и, возможно, то же самое для вас.

Bye!

0 голосов
/ 24 ноября 2011

Если честно, изменение атрибутов 3000 предметов должно быть легко для любого компьютера. Рафаэль использует setInterval для каждого анимированного элемента. После изменения атрибута элемента браузер заново рисует всю страницу. Это 2999 ненужных повторных розыгрышей.

Вот что я бы сделал: вместо использования анимации Рафаэля используйте цикл для изменения каждого элемента. Это немного сложнее, но это быстрее. Кроме того, вы можете изменить количество шагов в секунду. Если ваша анимация работает слишком медленно, просто уменьшите количество шагов в секунду.

Вот пример: http://jsfiddle.net/dqJps/25/

Надеюсь, это поможет.

0 голосов
/ 23 ноября 2011

Поскольку я в настоящее время не очень хорошо знаком с Rapael.js, я бы просто предложил в общем виде JavaScript, что вы можете создать changeRaphaelPathAttributeEvent, который вы будете генерировать каждый раз, когда вы хотите изменитьпути, с атрибутом изменения в качестве аргументов для указанного события.А затем присоедините обработчики событий к каждому из путей, которые будут выполнять изменение атрибута, если это возможно.

Таким образом, вы бы обошли проблему с циклом доступа ко всем переменным путей и изменения атрибутов.синхронно (что напрямую влияет на отзывчивость страницы при обработке);этот метод будет оказывать меньшее влияние на производительность, которую испытывает пользователь.

Примечание. Это просто решение, позволяющее обойти немедленное снижение производительности.Возможно, существуют другие решения, позволяющие свести к минимуму количество объектов, необходимых для доступа, о которых вам также следует подумать (и я не могу вам этого сказать, поскольку я не очень хорошо знаю Рафаэля).

...