HTML5 Canvas против SVG против div - PullRequest
438 голосов
/ 04 мая 2011

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

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

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

Ответы [ 8 ]

531 голосов
/ 04 мая 2011

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

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

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

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


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

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

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

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

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

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

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

Я сделал тестовые страницы 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 шириной в пиксель. Безумие наступает.
37 голосов
/ 26 января 2014

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

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

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

Fiddle: 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);
22 голосов
/ 28 февраля 2016

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

Canvas

SVG

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

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

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

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

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

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

16 голосов
/ 05 декабря 2015

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

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

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

13 голосов
/ 04 мая 2011

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

12 голосов
/ 07 апреля 2018

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

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

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

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

2 голосов
/ 03 марта 2018

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

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

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

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

...