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

114

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

http://www.planethunters.org/classify

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

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

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

d3.js , который вырос из Protovis, основан на SVG и должен лучше обрабатывать анимацию . Однако я сомневаюсь, насколько лучше и каков потолок его производительности. По этой причине я также рассматриваю возможность более полного пересмотра с использованием библиотеки на основе холста, такой как 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 в сочетании с рендерингом холста . Однако я не могу найти много документации по этому поводу в Интернете или связаться с OP этого сообщения. Если у кого-то есть опыт реализации такого рода реализации DOM-to-Canvas ( демонстрация , код ), я хотел бы услышать и от вас. Кажется, это хороший гибрид возможности манипулировать данными и иметь собственный контроль над тем, как их отображать (и, следовательно, производительность), но мне интересно, будет ли необходимость загружать все в DOM по-прежнему замедлять работу.

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

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

Эндрю Мао
источник
«Самое важное - это производительность, а второстепенный акцент делается на простоте добавления других взаимодействий» +1 за холст
Филипп
Вопрос в том, достаточно ли SVG в большинстве браузеров для 2k точек + других элементов диаграммы? Если это так и медлительность связана только с недостатками protovis, то я бы предпочел использовать SVG.
Эндрю Мао
1
Майк Босток уже дал хороший ответ. Для получения дополнительной информации вы можете проверить эти два ресурса: stackoverflow.com/questions/5882716/html5-canvas-vs-svg-vs-div/… blogs.msdn.com/b/ie/archive/2011/04/22 /…
Юмит
8
Последующие действия: я реализовал это с помощью гибридного подхода SVG / холста, где SVG заботится об осях и линиях сетки, а холст может очень быстро отображать точки. Это супер быстро!
Эндрю Мао

Ответы:

183

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

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

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

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

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

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

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

mbostock
источник
Вау, это был потрясающий ответ, и от самого мастера визуализации! Я думаю, что мне придется придерживаться семантического масштабирования, а на моем компьютере средство визуализации на основе холста намного быстрее, чем версия SVG при панорамировании / масштабировании (может быть, это связано с реализацией браузера?). То, что вы сказали об использовании SVG с холстом в качестве внутреннего цикла, - это именно то, что я хотел подтвердить, а примеры кода - просто приятный бонус. Спасибо!
Эндрю Мао,
Просто пришла в голову мысль попробовать примеры семантического масштабирования в разных браузерах: Chrome, оба довольно быстрые, я не вижу разницы; IE: SVG немного медленнее; Firefox (последний комментарий): SVG чертовски медленный по сравнению с холстом. Думаю, это тоже немного усложняет решение, но делает рендеринг холста безопасным выбором. Еще один вопрос: существенно ли влияет на производительность использование KineticJS вместо Canvas?
Эндрю Мао,
1
Эндрю, немного поздно, но вот мой опыт с FF: он наверстывает упущенное. Раньше я выполнял переходы FF 15 и D3 SVG, быстро начали замедляться. Но каждая новая версия становилась существенно быстрее. Сейчас я использую бета-версию FF 18, и она быстрее по сравнению с 17. Не уверен, что она такая же гладкая, как хром.
user2503795
@AndrewMao Привет, Эндрю, я столкнулся с ситуацией, когда кажется, что рендеринг является узким местом. Мне нужно панорамировать и масштабировать некоторые точки и около 6000 кривых. stackoverflow.com/questions/17907769/svg-path-rendering-speed/… Но я не совсем понимаю Бостока, когда он сказал: «Сохраняйте как можно больше в SVG и используйте Canvas только для« внутреннего цикла ». хотя посмотрел на четыре примера .. Не могли бы вы пролить свет на меня?
kakacii
@kakacii одинаково медленное преобразование во всех браузерах? Если это так, я бы сказал, что вы либо используете неправильный код, либо вы достигли пределов рендеринга браузера. Если бы вы могли опубликовать код, я смогу помочь. mbostock имел в виду использование SVG для простоты манипуляции и холста только по мере необходимости, поскольку его сложнее кодировать. Однако библиотеки, такие как KineticJS, до некоторой степени упростили это.
Эндрю Мао
8

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

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

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

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

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

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

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

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

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

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

Philipp
источник
7

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

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

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

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

При использовании профилировщика Chrome с CanvasJS память никогда не превышала 30 МБ, в то время как использование памяти Highcharts превышало 600 МБ.

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

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

Тем не менее, для автономных отчетов я бы выбрал Highcharts, поскольку его API более гибкий.

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

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

user432024
источник
3

Можно также заглянуть в Meteor Charts, который построен на основе сверхбыстрой инфраструктуры KineticJS: http://meteorcharts.com/

Эрик Роуэлл
источник
0

Я также обнаружил, что когда мы печатаем в PDF-файл страницу с графикой SVG, полученный PDF-файл по-прежнему содержит векторное изображение, а если вы печатаете страницу с графикой Canvas, изображение в полученном PDF-файле растрируется.

ostrokach
источник