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

476

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

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

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

Verdy
источник
13
Вы можете найти это интересным: мысли о том, когда использовать Canvas и SVG .
Роберт
1
Для тех, кто плохо знаком с этой технологией, это видео охватывает как SVG, так и Canvas, а также другие подробности о том, как это интегрируется в html5.
Пауло Буэно
12
Краткий ответ: Canvas для MS Paint, а SVG для MS Powerpoint. Холст растровый, SVG - векторный.
GetFree
2
Уважаемый читатель: возьмите все сравнения и утверждения здесь с недоверием и посмотрите дату постов и комментариев. Времена изменились и будут меняться. Относительная производительность и даже ваши параметры будут меняться. Например, большинство ответов были написаны, когда не было WebGL, что, безусловно, является альтернативой - через несколько лет оно тоже устареет, но на сегодняшний день это может быть очень актуально.
Себастьян
@ Себастьян, что бы вы порекомендовали сегодня? если задан базовый размер (например, 1280x800) и если вы готовы масштабировать элементы вручную в коде или постоянно использовать проценты, есть ли преимущество SVG в использовании DIV?
Crashalot

Ответы:

563

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

Вывод:

  • SVG, вероятно, лучше для приложений и приложений с небольшим количеством элементов (менее 1000? Зависит от действительности)
  • Canvas лучше подходит для тысяч объектов и осторожных манипуляций, но для его запуска требуется намного больше кода (или библиотеки).
  • HTML-элементы Div неуклюжи и не масштабируются, создание круга возможно только с закругленными углами, создание сложных форм возможно, но включает в себя сотни крошечных крошечных элементов Div шириной в пиксель. Безумие наступает.
Саймон Саррис
источник
4
Библиотека Cake - еще один пример создания подвижных объектов и анимации с объектами на холсте
SiggyF,
Неправильно: P div может масштабироваться, если браузер использует ускоренный CSS-движок hw, css art отличается от других, и помимо Canvas и SVG здесь правильный выбор, CSS art / div art - это именно тот случай, когда вам не нужно перегибать только небольшой оверлей: P
ShrekOverflow
Что касается DIV, если вы хотите создавать круги / специальные фигуры и не собираетесь менять свое изображение / спрайт должным образом, вы можете просто создать PNG и использовать его как background-image... Хотя вы можете делать подобные вещи в SVG / Canvas
luiges90
4
Что если вы создаете интерактивную карту? : p
Энтони
Это было создано с использованием (не вложенных) DIV и CSS 3D-преобразований, так что я бы сказал, что DIV совсем не медленные: youtube.com/watch?v=fzBC20B5dsk
Эрик Каплун,
39

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

Я обнаружил, что на моем 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 был безусловно самым эффективным, плюс автоматическое масштабирование на экранах сетчатки является огромным бонусом.
Фиджит
Кнут и @Fijjit вы рассматривали возможность использования DIV вместо SVG? если бы вам дали базовый размер (например, 1280x800), вы не могли бы вручную масштабировать DIV, чтобы они выглядели такими же резкими, как SVG? Спасибо за вашу помощь!
Crashalot
24

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

холст

SVG

  • Независимое разрешение
  • Поддержка обработчиков событий
  • Лучше всего подходит для приложений с большими областями рендеринга (Google Maps)
  • Медленный рендеринг, если сложный (все, что часто использует DOM, будет медленным)
  • Не подходит для игрового приложения
Лев четверка
источник
8
почему люди говорят, что Canvas зависит от разрешения? Я понимаю, что после того, как изображение было отображено, оно не масштабируется. но вы можете перерисовать изменения размера разрешения, так как же это разрешение не зависит?
Алекс Боллбах
@AlexBollbach - Canvas зависит от разрешения, поскольку для получения хороших результатов необходимо учитывать (зависеть) разрешение. С SVG вам нет дела до разрешения. Удачи в получении не зазубренных линий на принтере 2400DPI и рендеринге на основе Canvas. Нет проблем с SVG.
Себастьян
18

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

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

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

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

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

Умит
источник
17

Просто мои 2 цента относительно опции div.

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

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

Эрик Каплун
источник
14

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

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

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

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

Себастьян
источник
Пользователи Unix должны принять к сведению, что аппаратное ускорение по умолчанию отключено как в Firefox, так и в Chromium, что по-прежнему верно в середине 2019 года.
NVRM
@NVRM - это аппаратное ускорение CSS и SVG, а не декодирование видео. AFAIK первый был доступен в течение многих лет: Проверьте выход хрома: // gpu
Себастьян
layers.acceleration.force-enabledв Firefox речь идет не о декодировании видео. Это хорошо известный факт. Когда цикл завершен с использованием requestAnimationFrame, это другой уровень, позволяющий перерисовывать больше. Не о видео вообще.
NVRM
@NVRM - не могли бы вы предоставить ссылки на ошибки FF и Chromium для этих проблем с графическим процессором в Linux, пожалуйста? Также обратите внимание, что под «аппаратным ускорением» я имел в виду не только ускорение графического процессора, но также многопотоковую компоновку и анимацию, например, загрузку спиннеров, которые продолжают вращаться, когда JavaScript не работает или во время выполнения JS. С Canvas это невозможно, и по отношению к чистому «JavaScript» это действительно некое аппаратное ускорение (многопоточность), которое определенно доступно в Chrome и FF на всех платформах. Спасибо!
Себастьян
1
Подводя итог текущей ситуации: у меня работает на Chrome и Chromium. В линуксе В 2019 году на всех экземплярах я тестировал без специальной настройки. Firefox / Mozilla работает над этим для Linux , однако внепроцессный рендеринг не является чем-то новым для FF, и он всегда будет работать лучше с SVG, CSS и т. Д., Чем он может работать с Canvas.
Себастьян
13

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

Gaurav
источник
1
На самом деле использование простого HTML наиболее эффективно в сочетании с изображениями CSS.
Рэйнос
16
@Raynos: источник?
Янус Троелсен
3

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

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

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

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

Алиреза Фаттахи
источник