HTML5 Canvas против SVG против div

415

Каков наилучший подход для создания элементов "на лету" и возможности их перемещения? Например, предположим, что я хочу создать прямоугольник, круг и многоугольник, а затем выделить эти объекты и переместить их.

Я понимаю, что HTML5 содержит три элемента, которые могут сделать это возможным: svg, canvas и div. Для чего я хочу сделать, какой из этих элементов обеспечит лучшую производительность?

Чтобы сравнить эти подходы, я думал о создании трех визуально идентичных веб-страниц, каждая из которых имеет в них заголовок, нижний колонтитул, виджет и текстовый контент. Виджет на первой странице будет полностью создан с элементом canvas, второй - полностью с элементом svg, а третий с простым элементом div, HTML и CSS.

  • 12
    Вы можете найти это интересным: мысли о том, когда использовать Canvas и SVG .
  • 1
    Для тех, кто плохо знаком с этой технологией, это видео охватывает как SVG, так и Canvas, а также другие подробности о том, как это интегрируется в html5.
Показать ещё 9 комментариев
Теги:
svg
html5-canvas

8 ответов

516
Лучший ответ

Краткий ответ:

SVG будет проще для вас, так как выбор и перемещение его уже встроены. Объекты SVG являются объектами DOM, поэтому они имеют обработчики "click" и т.д.

DIVs в порядке, но неуклюжие и ужасно загружают производительность в больших количествах.

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


Длинный ответ:

HTML5 Холст - это просто поверхность рисования для бит-карты. Вы настроились на рисование (произнесите цвет и толщину линии), нарисуйте эту вещь, а затем холст не знает об этом: он не знает, где это или что вы только что нарисовали, это просто пиксели. Если вы хотите рисовать прямоугольники и перемещать их или выбирать, вам нужно закодировать все это с нуля, включая код, чтобы помнить, что вы их нарисовали.

SVG, с другой стороны, должен поддерживать ссылки на каждый объект, который он отображает. Каждый созданный вами элемент SVG/VML является реальным элементом в DOM. По умолчанию это позволяет вам лучше отслеживать элементы, которые вы создаете, и по умолчанию делает работу с вещами, такими как события мыши, но значительно замедляется, когда имеется большое количество объектов.

Эти ссылки SVG DOM означают, что некоторые действия, связанные с тем, что вы делаете, сделаны для вас. И SVG быстрее при рендеринге очень больших объектов, но медленнее при рендеринге многих объектов.

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

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

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

Я сделал тестовые страницы Canvas и HTML DIV, у обоих были подвижные "узлы". Узлы холста были объектами, которые я создал и отслеживал в Javascript. Узлами HTML были подвижные Divs.

Я добавил 100 000 узлов к каждому из моих двух тестов. Они выполнялись совершенно по-другому:

Вкладка теста HTML навсегда загрузилась (при минимальном времени менее 5 минут хром попросил убить страницу в первый раз). Менеджер задач Chrome говорит, что вкладка занимает 168 МБ. Он занимает 12-13% процессорного времени, когда я смотрю на него, 0%, когда я не смотрю.

Закладка Canvas загружается за одну секунду и занимает 30 МБ. Это также занимает 13% времени процессора все время, независимо от того, смотрит ли он на него. (Редактирование в 2013 году: они в основном исправили это)

Перетаскивание на HTML-странице более плавное, чего ожидает дизайн, так как текущая настройка должна перерисовывать ВСЕ каждые 30 миллисекунд в тесте Canvas. Для этого есть множество оптимизаций для Canvas. (аннулирование холста, являющееся самым легким, также отсекающим областями, выборочным перерисовкой и т.д., зависит только от того, насколько вы чувствуете себя реализацией)

Нет сомнений, что вы можете заставить Canvas быть быстрее при манипулировании объектами как divs в этом простом тесте и, конечно же, намного быстрее во время загрузки. Рисование/загрузка выполняется быстрее в Canvas и имеет гораздо больше возможностей для оптимизации (т.е. Исключая вещи, которые находятся вне экрана очень просто).

Вывод:

  • SVG, вероятно, лучше подходит для приложений и приложений с небольшим количеством элементов (менее 1000? зависит действительно)
  • Canvas лучше для тысяч объектов и тщательной манипуляции, но для его получения требуется гораздо больше кода (или библиотеки).
  • HTML Divs неуклюжие и не масштабируются, делая круг возможно только с закругленными углами, что делает сложные формы возможными, но включает в себя сотни крошечных крошечных пиксельных разделов. Приходит безумие.
  • 4
    Библиотека Cake - еще один пример создания подвижных объектов и анимации с объектами на холсте.
  • 0
    Неправильно: P div может масштабироваться, если браузер использует ускоренный CSS-движок hw, css art отличается от других, и помимо Canvas и SVG здесь правильный выбор, CSS art / div art - это именно тот случай, когда вам не нужно перегибать только небольшой оверлей: P
Показать ещё 6 комментариев
35

Чтобы добавить к этому, я делал приложение для диаграмм и изначально начал с canvas. Диаграмма состоит из множества узлов, и они могут стать довольно большими. Пользователь может перетаскивать элементы на диаграмме вокруг.

Я обнаружил, что на моем Mac для очень больших изображений SVG превосходен. У меня есть MacBook Pro 2013 13 "Retina, и он довольно хорошо работает на скрипке внизу. Изображение размером 6000x6000 пикселей и 1000 объектов. Подобную конструкцию на холсте мне было невозможно анимировать, когда пользователь перетаскивал объекты в диаграмма.

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

Скрипка: http://jsfiddle.net/knutsi/PUcr8/16/

Полноэкранный режим: http://jsfiddle.net/knutsi/PUcr8/16/embedded/result/

var wiggle_factor = 0.0;
nodes = [];

// create svg:
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute('style', 'border: 1px solid black');
svg.setAttribute('width', '6000');
svg.setAttribute('height', '6000');

svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink",
    "http://www.w3.org/1999/xlink");

document.body.appendChild(svg);


function makeNode(wiggle) {
    var node = document.createElementNS("http://www.w3.org/2000/svg", "g");
    var node_x = (Math.random() * 6000);
    var node_y = (Math.random() * 6000);
    node.setAttribute("transform", "translate(" + node_x + ", " + node_y +")");

    // circle:
    var circ = document.createElementNS("http://www.w3.org/2000/svg", "circle");
    circ.setAttribute( "id","cir")
    circ.setAttribute( "cx", 0 + "px")
    circ.setAttribute( "cy", 0 + "px")
    circ.setAttribute( "r","100px");
    circ.setAttribute('fill', 'red');
    circ.setAttribute('pointer-events', 'inherit')

    // text:
    var text = document.createElementNS("http://www.w3.org/2000/svg", "text");
    text.textContent = "This is a test! ÅÆØ";

    node.appendChild(circ);
    node.appendChild(text);

    node.x = node_x;
    node.y = node_y;

    if(wiggle)
        nodes.push(node)
    return node;
}

// populate with 1000 nodes:
for(var i = 0; i < 1000; i++) {
    var node = makeNode(true);
    svg.appendChild(node);
}

// make one mapped to mouse:
var bnode = makeNode(false);
svg.appendChild(bnode);

document.body.onmousemove=function(event){
    bnode.setAttribute("transform","translate(" +
        (event.clientX + window.pageXOffset) + ", " +
        (event.clientY + window.pageYOffset) +")");
};

setInterval(function() {
    wiggle_factor += 1/60;
    nodes.forEach(function(node) {

        node.setAttribute("transform", "translate(" 
                          + (Math.sin(wiggle_factor) * 200 + node.x) 
                          + ", " 
                          + (Math.sin(wiggle_factor) * 200 + node.y) 
                          + ")");        
    })
},1000/60);
  • 2
    Мы остановились и на SVG, отчаянно пытаясь заставить Canvas работать на нас. У нас очень большая диаграмма, и SVG был безусловно самым эффективным, плюс автоматическое масштабирование на экранах сетчатки является огромным бонусом.
  • 0
    Кнут и @Fijjit вы рассматривали возможность использования DIV вместо SVG? если бы вам дали базовый размер (например, 1280x800), вы не могли бы вручную масштабировать DIV, чтобы они выглядели такими же резкими, как SVG? Спасибо за вашу помощь!
22

Знание различий между SVG и Canvas было бы полезно при выборе правильного.

Холст

  • зависимое от разрешения
  • Нет поддержки обработчиков событий
  • Плохие возможности рендеринга текста
  • Вы можете сохранить результирующее изображение как .png или .jpg
  • Хорошо подходит для графических игр

SVG

  • Независимо от разрешения
  • Поддержка обработчиков событий
  • Лучше всего подходит для приложений с большими областями рендеринга (Google Maps).
  • Медленный рендеринг, если он сложный (все, что использует DOM, будет медленный)
  • Не подходит для игрового приложения.
  • 1
    Неудивительно, что игры чаще всего разрабатываются на Canvas.
  • 5
    почему люди говорят, что Canvas зависит от разрешения? Я понимаю, что после того, как изображение было отображено, оно не масштабируется. но вы можете перерисовать изменения разрешения, так почему же это разрешение не зависит?
18

Я согласен с выводами Саймона Сарриса:

Я сравнил некоторую визуализацию в Protovis (SVG) с Processingjs (Canvas), которые отображают > 2000 точек, а обработка js намного быстрее, чем protovis.

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

Существует также библиотека dojo.gfx набора инструментов dojo. Он обеспечивает уровень абстракции, и вы можете указать средство визуализации (SVG, Canvas, Silverlight). Это может быть также жизнеспособным выбором, хотя я не знаю, сколько накладных расходов добавляет дополнительный уровень абстракции, но это упрощает кодирование взаимодействий и анимаций и рендеринг-агностик.

Вот несколько интересных тестов:

16

Только мои 2 цента относительно опции divs.

Знаменитые/Infamous и SamsaraJS (и, возможно, другие) используют абсолютно позиционированные не вложенные div (с нетривиальным содержимым HTML/CSS) в сочетании с матрицей 2d/matrix3d ​​для позиционирования и 2D/3D-преобразованиями и обеспечивают стабильную 60FPS на умеренное мобильное оборудование, поэтому я бы сказал, что divs является медленным вариантом.

В Youtube и других местах имеется множество записей на экране высокопроизводительных 2D/3D объектов, работающих в браузере, причем все это элемент DOM, который вы можете проверить Element, на 60FPS (смешанный с WebGL для определенных эффектов, но а не для основной части рендеринга).

13

Для ваших целей я рекомендую использовать SVG, так как вы получаете события DOM, такие как обработка мыши, в том числе перетаскивание, включая, вам не нужно выполнять собственную перерисовку, и вам не нужно отслеживать состояние ваших объектов. Используйте Canvas, когда вам нужно делать манипуляции с растровым изображением и использовать обычный div, когда вы хотите манипулировать файлами, созданными в HTML. Что касается производительности, вы обнаружите, что современные браузеры теперь ускоряют все три, но этот холст получил наибольшее внимание до сих пор. С другой стороны, насколько хорошо вы пишете свой javascript, важно получить максимальную производительность с помощью холста, поэтому я по-прежнему рекомендую использовать SVG.

  • 1
    На самом деле использование простого HTML наиболее эффективно в сочетании с изображениями CSS.
  • 15
    @Raynos: источник?
9

Несмотря на то, что в большинстве ответов выше есть доля правды, я думаю, что они заслуживают обновления:

За эти годы производительность SVG значительно улучшилась, и теперь есть CSS-переходы и анимации с аппаратным ускорением для SVG, которые вообще не зависят от производительности JavaScript. Конечно, производительность JavaScript тоже улучшилась, а вместе с ней и производительность Canvas, но не так сильно, как SVG. Также в блоке есть "новый ребенок", который доступен практически во всех браузерах сегодня, а именно WebGL. Чтобы использовать те же слова, которые Саймон использовал выше: он опускает руки и Canvas, и SVG. Это не означает, что это должна быть технология перехода, так как работать с ней чудовищно, и она работает быстрее только в очень специфических случаях использования.

ИМХО для большинства случаев использования сегодня SVG дает наилучшее соотношение производительности и удобства использования. Визуализации должны быть действительно сложными (с точки зрения количества элементов) и одновременно очень простыми (для каждого элемента), чтобы Canvas и даже более того WebGL действительно сияли.

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

2

Во время поиска в Google я нашел хорошее объяснение об использовании и сжатии SVG и Canvas на http://teropa.info/blog/2016/12/12/graphics-in-angular-2.html.

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

  • SVG, как и HTML, использует сохраненную визуализацию: когда мы хотим нарисовать прямоугольник на экране, мы декларативно используем элемент в нашей DOM. Затем браузер нарисует прямоугольник, но он также создаст объект SVGRectElement в памяти, который представляет прямоугольник. Этот объект является чем-то, что нам остается манипулировать - оно сохраняется. Мы можем назначить ему различные позиции и размеры с течением времени. Мы также можем прикрепить слушателей событий, чтобы сделать их интерактивными.
  • Canvas использует немедленный рендеринг: когда мы рисуем прямоугольник, браузер немедленно отображает прямоугольник на экране, но никогда не будет никакого "объекта прямоугольника", который его представляет. В буфере холста есть только несколько пикселей. Мы не можем переместить прямоугольник. Мы можем только нарисовать еще один прямоугольник. Мы не можем отвечать на щелчки или другие события в прямоугольнике. Мы можем отвечать только на события на всем холсте.

Таким образом, canvas - это более низкоуровневый, ограничивающий API, чем SVG. Но есть и обратная сторона: с холстом вы можете сделать больше с тем же количеством ресурсов. Поскольку браузеру не нужно создавать и поддерживать в графе объектов в памяти все, что мы нарисовали, ему требуется меньше памяти и вычислительных ресурсов для рисования одной и той же визуальной сцены. Если у вас есть очень большая и сложная визуализация для рисования, Canvas может быть вашим билетом.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню