Холст HTML5 против SVG против div

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

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

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

Ответ 1

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

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 неуклюжие и не масштабируются, делая круг возможно только с закругленными углами, что делает сложные формы возможными, но включает в себя сотни крошечных крошечных пиксельных разделов. Приходит безумие.

Ответ 2

Чтобы добавить к этому, я делал приложение для диаграмм и изначально начал с 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);

Ответ 3

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

холст

SVG

  • Независимое разрешение
  • Поддержка обработчиков событий
  • Лучше всего подходит для приложений с большими областями рендеринга (Google Maps)
  • Медленный рендеринг, если сложный (все, что часто использует DOM, будет медленным)
  • Не подходит для игрового приложения

Ответ 4

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

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

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

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

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

Ответ 5

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

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

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

Ответ 6

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

Ответ 7

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

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

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

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

Ответ 8

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

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

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

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