Kanvas HTML5 vs. SVG vs. div

476

Apa pendekatan terbaik untuk membuat elemen dengan cepat dan mampu memindahkannya? Sebagai contoh, katakanlah saya ingin membuat persegi panjang, lingkaran, dan poligon, lalu pilih objek-objek itu dan pindahkan.

Saya mengerti bahwa HTML5 menyediakan tiga elemen yang memungkinkan ini: svg , canvas dan div . Untuk apa yang ingin saya lakukan, elemen mana yang akan memberikan kinerja terbaik?

Untuk membandingkan pendekatan ini, saya berpikir untuk membuat tiga halaman web yang identik secara visual yang masing-masing memiliki header, footer, widget, dan konten teks di dalamnya. Widget di halaman pertama akan dibuat seluruhnya dengan canvaselemen, yang kedua seluruhnya dengan svgelemen, dan yang ketiga dengan divelemen polos , HTML dan CSS.

verdy
sumber
13
Anda mungkin menemukan ini menarik: Pikiran tentang kapan harus menggunakan Canvas dan SVG .
robertc
1
Bagi Anda yang baru mengenal teknologi ini, video ini mencakup SVG dan Canvas dan detail lainnya tentang bagaimana hal tersebut terintegrasi pada html5.
Paulo Bueno
12
Jawaban singkat: Kanvas adalah untuk MS Paint karena SVG adalah untuk MS Powerpoint. Kanvas itu raster, SVG adalah vektorial.
GetFree
2
Pembaca yang terhormat: ambil semua perbandingan dan pernyataan di sini dengan sebutir garam dan lihat tanggal posting dan komentar. Waktu telah berubah dan akan berubah. Kinerja relatif dan bahkan opsi yang Anda miliki akan berubah. Misalnya, sebagian besar jawaban ditulis ketika tidak ada WebGL, yang pasti merupakan alternatif - itu akan usang dalam beberapa tahun, juga, tetapi pada hari ini mungkin sangat relevan.
Sebastian
@Sebastian yang akan Anda rekomendasikan hari ini? jika diberi ukuran dasar (mis., 1280x800) dan jika Anda bersedia untuk menskala elemen secara manual dalam kode atau menggunakan persentase sepanjang waktu, apakah ada keuntungan SVG untuk menggunakan DIV?
Crashalot

Jawaban:

563

Jawaban singkatnya:

SVG akan lebih mudah bagi Anda, karena pemilihan dan memindahkannya sudah ada di dalamnya. Objek SVG adalah objek DOM, sehingga mereka memiliki penangan "klik", dll.

DIV baik-baik saja tetapi kikuk dan mengerikan pemuatan kinerja pada jumlah besar.

Canvas memiliki performa tangan-ke-bawah terbaik, tetapi Anda harus menerapkan sendiri semua konsep status terkelola (pemilihan objek, dll), atau menggunakan perpustakaan.


Jawaban panjangnya:

HTML5 Canvas hanyalah sebuah permukaan gambar untuk bit-map. Anda mengatur untuk menggambar (Katakan dengan warna dan ketebalan garis), menggambar hal itu, dan kemudian Kanvas tidak memiliki pengetahuan tentang hal itu: Tidak tahu di mana itu atau apa itu yang baru saja Anda gambar, itu hanya piksel. Jika Anda ingin menggambar persegi panjang dan membuatnya bergerak atau dipilih maka Anda harus kode semua itu dari awal, termasuk kode untuk diingat bahwa Anda menggambar mereka.

SVG di sisi lain harus mempertahankan referensi ke setiap objek yang direndernya. Setiap elemen SVG / VML yang Anda buat adalah elemen nyata di DOM. Secara default ini memungkinkan Anda untuk melacak elemen yang Anda buat dan membuat berurusan dengan hal-hal seperti peristiwa mouse lebih mudah secara default, tetapi memperlambat secara signifikan ketika ada sejumlah besar objek

Referensi DOM SVG tersebut berarti bahwa beberapa langkah untuk menangani hal-hal yang Anda gambar dilakukan untuk Anda. Dan SVG lebih cepat saat merender objek yang sangat besar , tetapi lebih lambat saat merender banyak objek.

Sebuah game mungkin akan lebih cepat di Canvas. Program peta besar mungkin akan lebih cepat di SVG. Jika Anda ingin menggunakan Canvas, saya memiliki beberapa tutorial tentang cara membuat objek bergerak dan berjalan di sini .

Canvas akan lebih baik untuk hal-hal yang lebih cepat dan manipulasi bitmap berat (seperti animasi), tetapi akan mengambil lebih banyak kode jika Anda ingin banyak interaktivitas.

Saya telah menjalankan banyak angka pada gambar buatan DIV HTML versus gambar buatan kanvas. Saya dapat membuat posting besar tentang manfaat masing-masing, tetapi saya akan memberikan beberapa hasil tes yang relevan untuk dipertimbangkan untuk aplikasi spesifik Anda:

Saya membuat halaman pengujian Kanvas dan HTML DIV, keduanya memiliki "simpul" yang dapat dipindahkan. Node kanvas adalah objek yang saya buat dan catat di Javascript. Node HTML adalah Div yang dapat dipindahkan.

Saya menambahkan 100.000 node ke masing-masing dari dua tes saya. Mereka tampil sangat berbeda:

Tab pengujian HTML membutuhkan waktu lama untuk memuat (waktunya sedikit di bawah 5 menit, chrome diminta untuk membunuh halaman pertama kali). Pengelola tugas Chrome mengatakan bahwa tab tersebut menghabiskan 168MB. Butuh 12-13% waktu CPU ketika saya melihatnya, 0% ketika saya tidak melihat.

Tab Canvas dimuat dalam satu detik dan membutuhkan 30MB. Ini juga memakan waktu 13% dari waktu CPU sepanjang waktu, terlepas dari apakah seseorang melihatnya atau tidak. (2013 edit: Mereka sebagian besar sudah memperbaiki itu)

Menyeret di halaman HTML lebih halus, yang diharapkan oleh desain, karena pengaturan saat ini adalah untuk menggambar kembali SETIAP setiap 30 milidetik dalam tes Canvas. Ada banyak optimasi yang bisa didapat untuk Canvas untuk ini. (pembatalan kanvas menjadi yang termudah, juga memotong daerah, menggambar ulang selektif, dll. hanya tergantung pada seberapa banyak Anda ingin menerapkan)

Tidak ada keraguan Anda bisa mendapatkan Canvas menjadi lebih cepat pada manipulasi objek sebagai divs dalam tes sederhana itu, dan tentu saja jauh lebih cepat dalam waktu buka. Menggambar / memuat lebih cepat di Canvas dan memiliki ruang lebih banyak untuk optimisasi juga (yaitu, mengecualikan hal-hal yang di luar layar sangat mudah).

Kesimpulan:

  • SVG mungkin lebih baik untuk aplikasi dan aplikasi dengan beberapa item (kurang dari 1000? Sangat tergantung)
  • Kanvas lebih baik untuk ribuan objek dan manipulasi yang hati-hati, tetapi lebih banyak kode (atau perpustakaan) diperlukan untuk mendapatkannya dari tanah.
  • Div HTML adalah kikuk dan tidak skala, membuat lingkaran hanya mungkin dengan sudut-sudut bulat, membuat bentuk-bentuk kompleks dimungkinkan tetapi melibatkan ratusan div kecil selebar pixel. Kegilaan terjadi kemudian.
Simon Sarris
sumber
4
The Kue perpustakaan adalah contoh lain dari melakukan benda bergerak dan animasi dengan objek pada kanvas
SiggyF
Salah: Skala div Pyss jika browser menggunakan mesin CSS yang dipercepat, css art berbeda dan selain itu Canvas dan SVG adalah pilihan yang tepat di sini, CSS art / div art hanya ketika Anda tidak perlu overkill hanya overlay kecil: P
ShrekOverflow
Mengenai DIV, jika Anda ingin membuat lingkaran / bentuk khusus dan tidak akan mengubah gambar / sprite karena waktunya, Anda dapat membuat PNG dan menggunakannya sebagai background-image... Meskipun Anda dapat melakukan hal serupa di SVG / Canvas
luiges90
4
Bagaimana jika Anda membuat game peta interaktif? : p
Anthony
Ini dibuat menggunakan transformasi DIV dan CSS 3D (non-bersarang), jadi saya akan mengatakan DIV tidak lambat sama sekali: youtube.com/watch?v=fzBC20B5dsk
Erik Kaplun
39

Untuk menambah ini, saya sudah melakukan aplikasi diagram, dan awalnya dimulai dengan kanvas. Diagram terdiri dari banyak node, dan mereka bisa menjadi cukup besar. Pengguna dapat menyeret elemen dalam diagram sekitar.

Apa yang saya temukan adalah bahwa di Mac saya, untuk gambar yang sangat besar, SVG lebih unggul. Saya memiliki MacBook Pro 2013 13 "Retina, dan menjalankan biola di bawah ini dengan cukup baik. Gambarnya adalah 6000x6000 piksel, dan memiliki 1000 objek. Konstruksi serupa di kanvas tidak mungkin untuk menghidupkan bagi saya ketika pengguna menyeret objek di sekitar diagram.

Pada layar modern Anda juga harus memperhitungkan resolusi yang berbeda, dan di sini SVG memberi Anda semua ini secara gratis.

Fiddle: http://jsfiddle.net/knutsi/PUcr8/16/

Layar penuh: 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);
knut
sumber
2
Kami juga memilih SVG, setelah berusaha mati-matian untuk membuat Canvas bekerja untuk kami. Kami memiliki diagram yang sangat besar dan SVG adalah yang paling efisien, ditambah penskalaan otomatis pada layar retina adalah bonus besar.
Fijjit
knut dan @ Fijjit apakah Anda mempertimbangkan untuk menggunakan DIV daripada SVG? jika diberi ukuran dasar (mis., 1280x800) tidak bisakah Anda skala DIV secara manual sehingga mereka terlihat setajam SVG? terima kasih atas bantuan Anda!
Crashalot
24

Mengetahui perbedaan antara SVG dan Canvas akan sangat membantu dalam memilih yang tepat.

Kanvas

SVG

  • Resolusi independen
  • Dukungan untuk penangan acara
  • Paling cocok untuk aplikasi dengan area render besar (Google Maps)
  • Slow rendering if complex (apa pun yang menggunakan DOM banyak akan lambat)
  • Tidak cocok untuk aplikasi game
Leo The Four
sumber
8
mengapa orang mengatakan bahwa Canvas bergantung pada resolusi? saya mengerti bahwa begitu bitmap telah di-render, ia tidak dapat menskala dengan baik. tetapi Anda dapat menggambar ulang pada perubahan ukuran resolusi, jadi bagaimana tidakkah resolusi itu independen?
Alex Bollbach
@AlexBollbach - Canvas bergantung pada resolusi, karena Anda harus mempertimbangkan (tergantung) pada resolusi untuk mendapatkan hasil yang baik. Dengan SVG Anda tidak peduli tentang resolusi. Semoga berhasil dengan mendapatkan garis non-jaggy pada printer 2400DPI dan rendering berbasis Canvas. Tidak ada masalah dengan SVG.
Sebastian
18

Saya setuju dengan kesimpulan Simon Sarris:

Saya telah membandingkan beberapa visualisasi dalam Protovis (SVG) dengan Processingjs (Canvas) yang menampilkan> 2000 poin dan pemrosesan js jauh lebih cepat daripada protovis.

Menangani acara dengan SVG tentu saja jauh lebih mudah karena Anda dapat melampirkannya ke objek. Di Kanvas Anda harus melakukannya secara manual (periksa posisi mouse, dll) tetapi untuk interaksi sederhana seharusnya tidak sulit.

Ada juga perpustakaan dojo.gfx dari dojo toolkit. Ini memberikan lapisan abstraksi dan Anda dapat menentukan renderer (SVG, Canvas, Silverlight). Itu mungkin juga merupakan pilihan yang layak walaupun saya tidak tahu berapa banyak overhead yang ditambahkan lapisan abstraksi tambahan tetapi membuatnya mudah untuk interaksi kode dan animasi dan renderer-agnostik.

Berikut ini beberapa tolok ukur yang menarik:

"Tuh
sumber
17

Hanya 2 sen saya mengenai opsi divs.

Terkenal / Terkenal dan SamsaraJS (dan mungkin yang lain) menggunakan div non-bersarang yang diposisikan benar-benar (dengan konten HTML / CSS non-sepele), dikombinasikan dengan matrix2d / matrix3d ​​untuk penentuan posisi dan transformasi 2D / 3D, dan mencapai 60FPS yang stabil pada perangkat keras seluler moderat , jadi saya akan berdebat menentang divs menjadi pilihan lambat.

Ada banyak rekaman layar di Youtube dan di tempat lain, hal-hal 2D / 3D berkinerja tinggi berjalan di browser dengan semuanya menjadi elemen DOM yang Anda dapat Periksa Elemen pada, di 60FPS (dicampur dengan WebGL untuk efek tertentu, tetapi tidak untuk bagian utama dari rendering).

Erik Kaplun
sumber
14

Meskipun masih ada kebenaran pada sebagian besar jawaban di atas, saya pikir mereka layak mendapat pembaruan:

Selama bertahun-tahun kinerja SVG telah meningkat pesat dan sekarang ada transisi dan animasi CSS yang dipercepat perangkat keras untuk SVG yang tidak bergantung pada kinerja JavaScript sama sekali. Tentu saja kinerja JavaScript juga meningkat, dan dengan itu kinerja Canvas, tetapi tidak sebanyak SVG yang ditingkatkan. Juga ada "anak baru" di blok yang tersedia di hampir semua browser hari ini dan itu adalah WebGL . Untuk menggunakan kata-kata yang sama yang digunakan Simon di atas: Ini mengalahkan Canvas dan SVG . Ini tidak berarti itu harus menjadi teknologi canggih, karena ini adalah binatang buas untuk bekerja dengan dan itu hanya lebih cepat dalam kasus penggunaan yang sangat spesifik.

IMHO untuk sebagian besar kasus penggunaan saat ini, SVG memberikan rasio kinerja / kegunaan terbaik. Visualisasi harus sangat kompleks (berkenaan dengan jumlah elemen) dan sangat sederhana pada saat yang sama (per elemen) sehingga Canvas dan bahkan lebih lagi WebGL benar-benar bersinar.

Dalam jawaban untuk pertanyaan serupa saya memberikan lebih banyak detail, mengapa saya berpikir bahwa kombinasi ketiga teknologi kadang-kadang adalah pilihan terbaik yang Anda miliki.

Sebastian
sumber
Pengguna Unix harus memperhatikan bahwa akselerasi perangkat keras dinonaktifkan secara default di Firefox dan Chromium, masih berlaku di pertengahan 2019.
NVRM
@NVRM - ini tentang akselerasi perangkat keras CSS dan SVG, bukan tentang decoding video. AFAIK yang pertama telah tersedia selama bertahun-tahun: Periksa output chrome: // gpu
Sebastian
layers.acceleration.force-enableddi Firefox bukan tentang decoding video. Itu fakta yang sudah diketahui. Ketika selesai loop menggunakan requestAnimationFrame adalah level lain, memungkinkan cara pengecatan lebih banyak. Sama sekali tidak tentang video.
NVRM
@NVRM - bisakah Anda memberikan tautan ke bug FF dan Chromium untuk masalah GPU ini di Linux? Perhatikan juga bahwa dengan "akselerasi perangkat keras", saya tidak hanya mengacu pada akselerasi GPU, tetapi juga penggabungan dan animasi multi-ulir, seperti misalnya pemintal pemintal yang terus berputar saat tidak ada JavaScript yang berjalan atau saat JS sedang dieksekusi. Ini tidak mungkin dengan Canvas dan relatif terhadap "JavaScript" murni, ini memang semacam akselerasi perangkat keras (multi-threading) yang pasti tersedia di Chrome dan FF di semua platform. Terima kasih!
Sebastian
1
Singkatnya situasi saat ini: Berfungsi untuk saya di Chrome dan Chromium. Di Linux. Pada 2019. Pada semua contoh saya diuji tanpa konfigurasi khusus. Firefox / Mozilla sedang mengerjakannya untuk Linux , namun dari proses rendering bukan sesuatu yang baru untuk FF, baik dan akan selalu bekerja lebih baik dengan SVG, CSS, dll daripada yang bisa untuk Canvas.
Sebastian
13

Untuk tujuan Anda, saya sarankan menggunakan SVG, karena Anda mendapatkan acara DOM, seperti penanganan mouse, termasuk seret dan lepas, termasuk, Anda tidak harus menerapkan redraw sendiri, dan Anda tidak harus melacak status benda-benda Anda. Gunakan Kanvas ketika Anda harus melakukan manipulasi gambar bitmap dan gunakan div reguler ketika Anda ingin memanipulasi hal-hal yang dibuat dalam HTML. Mengenai kinerja, Anda akan mendapati bahwa peramban modern sekarang mempercepat ketiganya, tetapi kanvas itu telah mendapatkan perhatian terbesar sejauh ini. Di sisi lain, seberapa baik Anda menulis javascript sangat penting untuk mendapatkan kinerja terbaik dengan kanvas, jadi saya tetap merekomendasikan menggunakan SVG.

Gaurav
sumber
1
Sebenarnya menggunakan HTML biasa adalah yang paling berprestasi dalam kombinasi dengan gambar CSS.
Raynos
16
@ Raynos: Sumber?
Janus Troelsen
3

Sementara googling saya menemukan penjelasan yang baik tentang penggunaan dan kompresi SVG dan Canvas di http://teropa.info/blog/2016/12/12/graphics-in-angular-2.html

Semoga ini bisa membantu:

  • SVG, seperti HTML, menggunakan rendering yang dipertahankan : Ketika kami ingin menggambar persegi panjang di layar, kami secara deklaratif menggunakan elemen dalam DOM kami. Browser kemudian akan menggambar persegi panjang, tetapi itu juga akan membuat SVGRectElement dalam memori objek yang mewakili persegi panjang. Objek ini adalah sesuatu yang menempel di sekitar kita untuk memanipulasi - itu dipertahankan. Kami dapat menetapkan posisi dan ukuran yang berbeda dari waktu ke waktu. Kami juga dapat melampirkan pendengar acara untuk menjadikannya interaktif.
  • Canvas menggunakan rendering langsung : Ketika kita menggambar persegi panjang , browser segera merender persegi panjang di layar, tetapi tidak akan pernah ada "objek persegi panjang" yang mewakilinya. Hanya ada banyak piksel di buffer kanvas. Kami tidak bisa memindahkan persegi panjang. Kami hanya bisa menggambar persegi panjang lain. Kami tidak dapat menanggapi klik atau acara lain pada persegi panjang. Kami hanya dapat menanggapi acara di seluruh kanvas .

Jadi kanvas lebih rendah, API restriktif daripada SVG. Tapi ada sisi negatifnya, yaitu dengan kanvas Anda dapat melakukan lebih banyak dengan jumlah sumber daya yang sama. Karena browser tidak harus membuat dan memelihara grafik objek dalam-memori dari semua hal yang telah kami buat, browser ini membutuhkan lebih sedikit memori dan sumber daya komputasi untuk menggambar adegan visual yang sama. Jika Anda memiliki visualisasi gambar yang sangat besar dan kompleks, Canvas mungkin menjadi tiket Anda.

Alireza Fattahi
sumber