HTML5 Canvas vs. SVG vs. div


476

Який найкращий підхід для створення елементів на льоту та можливість їх переміщення? Наприклад, скажімо, що я хочу створити прямокутник, коло та багатокутник, а потім виділити ці об’єкти і перемістити їх.

Я розумію, що HTML5 пропонує три елементи, які можуть зробити це можливим: svg , canvas та div . Що я хочу зробити, який із цих елементів забезпечить найкращі показники?

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



1
Для тих, хто з вас не знайомий з цією наукою, це відео охоплює як SVG, так і Canvas та інші деталі про те, як це інтегрується в html5.
Пауло Буено

12
Коротка відповідь: Canvas - це MS Paint, а SVG - MS Powerpoint. Полотно растрове, SVG - векторне.
GetFree

2
Шановний читачу: візьміть тут всі порівняння та заяви із зерном солі та подивіться дату публікацій та коментарів. Часи змінилися і будуть змінюватися. Відносна продуктивність і навіть варіанти, які у вас є, зміниться. Наприклад, більшість відповідей там, де написано, коли не було WebGL, що, безумовно, є альтернативою - воно також застаріє через кілька років, але на сьогодні це може бути дуже актуальним.
Себастьян

@Sebastian, що б ти порадив сьогодні? якщо вам заданий базовий розмір (наприклад, 1280x800) і якщо ви готові масштабувати елементи вручну в коді або використовувати відсотки весь час, чи є перевага SVG використовувати DIV?
Crashalot

Відповіді:


563

Коротка відповідь:

SVG буде простішим для вас, оскільки вибір і переміщення його вже вбудовані. SVG-об’єкти - DOM-об'єкти, тому вони мають обробку "клацання" тощо.

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

Полотно має найкращі результати роботи, але вам потрібно реалізувати всі концепції керованого стану (вибір об'єкта тощо) або скористатися бібліотекою.


Довга відповідь:

HTML5 Canvas - це просто поверхня для малювання бітової карти. Ви налаштовуєтесь малювати (скажіть із кольором та товщиною ліній), малюєте цю річ, і тоді Полотно не знає про цю річ: воно не знає, де воно, або що це, що ви тільки що намалювали, це просто пікселі. Якщо ви хочете намалювати прямокутники і змусити їх рухатись чи вибирати їх, вам доведеться кодувати все це з нуля, включаючи код, щоб пам’ятати, що ви їх намалювали.

SVG, з іншого боку, повинен підтримувати посилання на кожен об'єкт, який він надає. Кожен створений вами SVG / VML-елемент є реальним елементом у DOM. За замовчуванням це дозволяє вам набагато краще відслідковувати створені елементи та полегшує поводження з такими речами, як події миші, за замовчуванням, але це значно сповільнюється при наявності великої кількості об'єктів

Ці посилання на SVG DOM означають, що певна робота з речами, які ви малюєте, зроблена саме для вас. І SVG швидше, коли рендерують дійсно великі об'єкти, але повільніше, коли багато рендерує.

Гра, можливо, буде швидшою на Canvas. Величезна програма з картами, мабуть, буде швидшою у SVG. Якщо ви хочете використовувати Canvas, у мене є деякі підручники з отримання рухомих об'єктів і працює тут .

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

Я провів купу чисел на малюнку, виготовленому HTML 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 бути швидшим при маніпулюванні об'єктом, як діви в тому простому тесті, і, звичайно, набагато швидше за час завантаження. Малювання / завантаження швидше в Canvas і також має набагато більше можливостей для оптимізацій (тобто виключити речі, які перебувають поза екраном, дуже просто).

Висновок:

  • SVG, мабуть, кращий для додатків і додатків із кількома елементами (менше 1000? Дійсно залежить)
  • Полотно краще для тисяч предметів і ретельних маніпуляцій, але потрібно набагато більше коду (або бібліотеки), щоб зняти його з землі.
  • HTML Divs є незграбними і не масштабуються, зробити коло можливо лише закругленими кутами, зробити складні форми можливо, але передбачає сотні крихітних крихітних пікселів. Настає божевілля.

4
Бібліотека тортів - ще один приклад робити переміщувані об’єкти та анімації з предметами на полотні
SiggyF

Неправильно: P Div може масштабуватися, якщо браузер використовує hw-прискорений CSS-механізм, CSS-арт відрізняється, і крім Canvas і SVG є правильним вибором тут, CSS art / div art - це просто тоді, коли вам не потрібно переборщити лише невелику накладку: P
ShrekOverflow

Що стосується DIVs, якщо ви хочете робити кола / спеціальні фігури і не збираєтесь змінювати своє зображення / спрайт із часом, ви можете просто створити 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 дає вам все це безкоштовно.

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);

2
Ми також влаштувались на SVG, після того, як відчайдушно намагалися змусити Canvas працювати на нас. У нас дуже велика діаграма, і SVG на сьогодні був найбільш ефективним, плюс автоматичне масштабування на екранах сітківки є величезним бонусом.
Fijjit

knut та @Fijjit Ви розглядали можливість використання DIVs замість SVG? якщо ви задали базовий розмір (наприклад, 1280x800), не вдалося б ви вручну масштабувати DIV, щоб вони виглядали так само чітко, як SVG? спасибі за вашу допомогу!
Crashalot

24

Знання відмінностей між SVG та Canvas було б корисним у виборі правильного.

Полотно

SVG

  • Дозвіл незалежний
  • Підтримка обробників подій
  • Найкраще підходить для програм із великими зонами візуалізації (Карти Google)
  • Повільна візуалізація, якщо складна (все, що багато використовує DOM, буде повільним)
  • Не підходить для ігор

8
чому люди кажуть, що полотно залежить від роздільної здатності? я розумію, що після того, як ракетна картинка була виведена, вона не масштабується добре. але ви можете перемальовувати зміни розміру роздільної здатності, тож як ця роздільна здатність не залежить?
Алекс Боллбах

@AlexBollbach - Полотно залежить від роздільної здатності, тому що для отримання хороших результатів потрібно врахувати (залежно) від роздільної здатності. З SVG вам не байдуже рішення. Удачі в отриманні нечітких ліній на принтері 2400DPI та візуалізації на основі Canvas. Немає проблем із SVG.
Себастьян

18

Я згоден з висновками Саймона Сарріса:

Я порівняв деяку візуалізацію в Protovis (SVG) з Processingjs (Canvas), який відображає> 2000 точок і Processjs набагато швидше, ніж protovis.

Звичайно, обробка подій за допомогою SVG набагато легша, оскільки ви можете прикріпити їх до об'єктів. У Canvas ви повинні робити це вручну (перевірити положення миші тощо), але для простої взаємодії це не повинно бути важким.

Існує також бібліотека dojo.gfx інструментарію dojo. Він надає шар абстракції, і ви можете вказати візуалізатор (SVG, Canvas, Silverlight). Це може бути також життєздатним вибором, хоча я не знаю, скільки додає додатковий шар абстракції, але це полегшує кодування взаємодій та анімацій і є рендерінг-агностиком.

Ось кілька цікавих орієнтирів:


17

Тільки мої 2 копійки щодо варіанту divs.

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

На Youtube та інших місцях є багато записів на екрані, у браузері працює високоефективний 2D / 3D матеріал, у якому все є елементом DOM, на який можна перевірити елемент , на 60 FPS (змішується з WebGL для певних ефектів, але не для основна частина візуалізації).


14

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

Протягом багатьох років продуктивність SVG значно покращилася, і тепер є перехід CSS та анімації для SVG , прискорені апаратним забезпеченням, які взагалі не залежать від продуктивності JavaScript. Звичайно, продуктивність JavaScript також покращилася, а з цим і продуктивність Canvas, але не настільки, наскільки покращився SVG. Також на блоці є "новий малюк", який доступний майже у всіх браузерах сьогодні, а це WebGL . Щоб використати ті самі слова, які Саймон вживав вище: Це б'є і Canvas, і SVG руками вниз. Це не означає, що це повинна бути нова технологія, оскільки це звір, з яким працювати, і це лише швидше у дуже конкретних випадках використання.

IMHO для більшості випадків використання сьогодні SVG дає найкраще співвідношення продуктивності та зручності використання. Візуалізації повинні бути дійсно складними (щодо кількості елементів) і водночас дуже простими (на елемент), щоб полотно і навіть більше 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. У Linux. У 2019 році я перевіряв без будь-якої спеціальної конфігурації. Firefox / Mozilla працює над цим для Linux , однак виведення з процесу не є чимось новим для FF, і завжди буде краще працювати з SVG, CSS тощо, ніж це може бути для Canvas.
Себастьян

13

Для ваших цілей я рекомендую використовувати SVG, оскільки ви отримуєте події DOM, наприклад, обробку миші, включаючи перетягування та перетягування, вам не потрібно реалізовувати власне перемальовування, і вам не потрібно стежити за станом ваші об’єкти. Використовуйте Canvas, коли вам потрібно виконати маніпулювання зображеннями растрових зображень та використовувати звичайний div, коли ви хочете маніпулювати речами, створеними в HTML. Щодо продуктивності, ви побачите, що сучасні браузери зараз прискорюють усі три, але до цього полотна привернули найбільшу увагу. З іншого боку, наскільки добре ви пишете свій JavaScript, вирішальне значення для отримання максимальної продуктивності на полотні, тому я все-таки рекомендую використовувати SVG.


1
Насправді використання простого HTML є найбільш ефективним у поєднанні із зображеннями CSS.
Райнос

16
@Raynos: Джерело?
Янус Трольсен

3

Під час googling я знаходжу гарне пояснення щодо використання та стиснення SVG та Canvas на веб-сайті http://teropa.info/blog/2016/12/12/graphics-in-angular-2.html

Сподіваюся, що це допомагає:

  • SVG, як і HTML, використовує збережену візуалізацію : коли ми хочемо намалювати прямокутник на екрані, ми декларативно використовуємо елемент у нашій DOM. Потім браузер намалюватиме прямокутник, але він також створить об'єкт SVGRectElement в пам'яті, який представляє прямокутник. Цей об’єкт - це те, що нам заважає маніпулювати - він зберігається. З часом ми можемо присвоювати йому різні положення та розміри. Ми також можемо підключити слухачів подій, щоб зробити його інтерактивним.
  • Полотно використовує негайне візуалізацію : Коли ми малюємо прямокутник , браузер негайно виводить прямокутник на екран, але жодного «об’єкта прямокутника», який би його представляв, ніколи не буде. У буфері канви просто купа пікселів. Ми не можемо перемістити прямокутник. Ми можемо намалювати лише інший прямокутник. Ми не можемо реагувати на кліки чи інші події прямокутника. Ми можемо реагувати лише на події на цілому полотні .

Отже, canvas є більш низьким рівнем обмеження API, ніж SVG. Але в цьому є зворотний бік, який полягає в тому, що з полотном ви можете зробити більше з однаковою кількістю ресурсів. Оскільки веб-переглядачу не потрібно створювати та підтримувати графік об'єкта в пам'яті всіх речей, які ми намалювали, йому потрібно менше пам'яті та ресурсів обчислень, щоб намалювати ту саму візуальну сцену. Якщо у вас дуже велика і складна візуалізація для малювання, Canvas може стати вашим квитком.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.