Быстрые и гибкие интерактивные диаграммы/графики: SVG, Canvas, другое?

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

http://www.planethunters.org/classify

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

Я хотел бы сделать некоторые обновления для интерфейса, а также изменить базовую технологию визуализации, чтобы быть более отзывчивыми с анимацией и взаимодействием. Из следующей статьи кажется, что выбор между другой библиотекой на основе SVG или на основе холста:

http://www.sitepoint.com/how-to-choose-between-canvas-and-svg/

d3.js, который вырос из Protovis, основан на SVG и должно быть лучше для рендеринга анимации. Тем не менее, я сомневаюсь в том, насколько лучше и каков его потолок производительности. По этой причине я также рассматриваю более полную перестройку, используя библиотеку на основе canvas, такую ​​как KineticJS. Однако, прежде чем я слишком далеко буду использовать тот или иной подход, я хотел бы услышать от кого-то, кто сделал подобное веб-приложение с этим большим количеством данных и получил свое мнение.

Самая важная вещь - производительность, с упором на удобство добавления других функций взаимодействия и программирования анимации. Вероятно, будет не более 2000 точек одновременно с этими небольшими барами ошибок на каждом из них. Масштабирование, выключение и панорамирование вокруг должны быть плавными. Если последние библиотеки SVG достойны этого, то, возможно, простота использования d3 перевешивает увеличенную настройку для KineticJS и т.д. Но если есть огромное преимущество в производительности использования холста, особенно для людей с более медленными компьютерами, тогда я определенно предпочел бы пойти таким образом.

Пример приложения, сделанного NYTimes, который использует SVG, но все равно анимируется приемлемо гладко: http://www.nytimes.com/interactive/2012/05/17/business/dealbook/how-the-facebook-offering-compares.html. Если я смогу получить эту производительность и не буду писать свой собственный код рисования холста, я бы, вероятно, пошел на SVG.

Я заметил, что некоторые пользователи использовали гибрид d3.js манипуляции в сочетании с рендерингом canvas. Однако я не могу найти много документации об этом онлайн или связаться с OP этого сообщения. Если у кого-то есть опыт выполнения такого типа DOM-to-Canvas (demo, код), я хотел бы также услышать от вас. Кажется, это хороший гибрид, позволяющий манипулировать данными и настраивать контроль над их рендерингом (и, следовательно, производительность), но мне интересно, стоит ли загружать все в DOM, все еще замедляет работу.

Я знаю, что есть некоторые существующие вопросы, похожие на это, но никто из них точно не спрашивает одно и то же. Благодарим за помощь.

Последующие действия: реализация, которую я закончил, находится на https://github.com/zooniverse/LightCurves

Ответ 1

К счастью, рисование 2000 кругов - довольно простой пример для тестирования. Итак, вот четыре возможных реализации: два из Canvas и SVG:

В этих примерах используется D3 поведение масштабирования для реализации масштабирования и панорамирования. Помимо того, отображаются ли круги в Canvas или SVG, другим важным отличием является использование геометрического или семантического масштабирования.

Геометрическое масштабирование означает, что вы применяете одно преобразование ко всему окну просмотра: при увеличении масштаба круги становятся больше. Семантическое масштабирование контрастностью означает, что вы применяете преобразования к каждому кругу индивидуально: когда вы увеличиваете масштаб, круги остаются одного размера, но они распространяются. В Planethunters.org в настоящее время используется семантическое масштабирование, но может быть полезно рассмотреть другие случаи.

Геометрическое масштабирование упрощает реализацию: вы применяете перевод и масштабируете один раз, а затем все круги повторно отображаются. Реализация SVG особенно проста, обновляя один атрибут "transform". Производительность обоих геометрических примеров масштабирования кажется более чем достаточной. Для семантического масштабирования вы заметите, что D3 значительно быстрее, чем Protovis. Это происходит потому, что он делает намного меньше работы для каждого события масштабирования. (Версия Protovis должна пересчитывать все атрибуты для всех элементов.) Семантическое масштабирование на основе Canvas немного более zippy, чем SVG, но семантическое масштабирование SVG все еще чувствует себя отзывчивым.

Тем не менее, нет никакой волшебной пули для производительности, и эти четыре возможных подхода не начинают охватывать все пространство возможностей. Например, вы можете комбинировать геометрическое и семантическое масштабирование, используя геометрические подход для панорамирования (обновление атрибута "transform" ) и только перерисовка отдельных кругов при масштабировании. Возможно, вы даже можете объединить один или несколько из этих методов с преобразованиями CSS3, чтобы добавить некоторое аппаратное ускорение (как в иерархическом примере связывания краев), хотя это может быть сложным для реализации и может создавать визуальные артефакты.

Тем не менее, мое личное предпочтение заключается в сохранить как можно больше в SVG и использовать Canvas только для "внутреннего цикла", когда рендеринг является узким местом. У SVG есть так много удобств для разработки, таких как CSS, data-join и инспектор элементов, что часто преждевременная оптимизация начинается с Canvas. Объединение холста с SVG, как и в визуализации Facebook IPO, которое вы связываете, - это гибкий способ сохранить большинство этих удобств, сохраняя при этом наилучшую производительность. Я также использовал эту технику в Cubism.js, где особый случай визуализации временных рядов хорошо поддается растровому кэшированию.

Как показывают эти примеры, вы можете использовать D3 с Canvas, хотя части D3 являются специфичными для SVG. Смотрите также этот силовой график и этот пример обнаружения столкновений.

Ответ 2

Я думаю, что в вашем случае решение между холстом и svg не похоже на решение между "верхом на лошади" или вождением "Porsche". Для меня это больше похоже на решение о цвете автомобилей.

Позвольте мне объяснить: Предполагая, что на основе структуры операции

  • нарисуйте звезду,
  • добавить звездочку и
  • удалить звездочку

взять линейное время. Итак, если ваше решение фреймворка было хорошим, оно немного быстрее, иначе немного медленнее.

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

Что я хочу сказать, так это то, что основа проблемы приводит к основной проблеме вычислительной геометрии, а именно: диапазон поиска и еще один компьютерной графики: уровень детализации.

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

Как вы заявили, что самое главное - производительность, чем я хотел бы использовать холст, потому что он работает без операций DOM. Он также предлагает возможность использовать webGL, что значительно увеличивает производительность графики.

Кстати: вы проверили paper.js? Он использует холст, но эмулирует векторную графику.

PS: В этой книге вы можете найти очень подробное обсуждение графики в Интернете, технологий, плюсов и минусов холста, SVG и DHTML.

Ответ 3

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

Мы попробовали Highcharts (svg) и Canvasjs. Хотя Highcharts является фантастическим API-интерфейсом и предлагает больше возможностей, мы решили использовать Canvasjs.

Нам нужно было отображать не менее 15 минут данных на диаграмму (с возможностью выбора диапазона максимум два часа).

Итак, в течение 15 минут: 900 точек (точка данных в секунду) x2 (диаграмма комбинации строк и баров) x4 диаграммы = всего 7200 баллов.

Используя хром-профилировщик, с Canvasjs память никогда не превышала 30 МБ, а использование памяти Highcharts превышало 600 МБ.

Также с временем обновления 5 секунд рендеринг Canvasjs был более гибким, чем Highcharts.

Мы использовали один таймер (setInterval 5 секунд), чтобы сделать 4 вызова API REST, чтобы вытащить данные с серверного сервера, подключенного к Elasticsearch. Каждая диаграмма, обновленная как данные, получена JQuery.post().

Что касается оффлайновых отчетов, я бы пошел с Highcharts с его более гибким API.

Также есть диаграммы Zing, которые утверждают, что используют SVG или Canvas, но не смотрели на них.

Холст следует учитывать, когда производительность действительно критическая. SVG для гибкости. Не то, что каркасы canvas не являются гибкими, но требует больше работы для каркаса canvas для получения той же функциональности, что и структура svg.

Ответ 4

Можно также посмотреть на Meteor Charts, который построен на вершине uber быстрой инфраструктуры KineticJS: http://meteorcharts.com/