Bagan / grafik interaktif yang cepat dan responsif: SVG, Canvas, lainnya?

114

Saya mencoba memilih teknologi yang tepat untuk digunakan untuk memperbarui proyek yang pada dasarnya menampilkan ribuan titik dalam grafik yang dapat diperbesar dan dapat dipindai. Implementasi saat ini, menggunakan Protovis, berkinerja buruk. Lihat disini:

http://www.planethunters.org/classify

Ada sekitar 2000 titik saat diperkecil sepenuhnya. Coba gunakan pegangan di bagian bawah untuk memperbesar sedikit, dan seret untuk menjelajah. Anda akan melihat bahwa itu cukup berombak dan penggunaan CPU Anda mungkin naik hingga 100% pada satu inti kecuali Anda memiliki komputer yang sangat cepat. Setiap perubahan ke area fokus memanggil gambar ulang ke protovis yang sangat lambat dan lebih buruk dengan lebih banyak titik yang ditarik.

Saya ingin membuat beberapa pembaruan pada antarmuka serta mengubah teknologi visualisasi yang mendasari menjadi lebih responsif dengan animasi dan interaksi. Dari artikel berikut, sepertinya pilihannya adalah antara pustaka berbasis SVG lainnya, atau pustaka berbasis kanvas:

http://www.sitepoint.com/how-to-choose-between-canvas-and-svg/

d3.js , yang tumbuh dari Protovis, berbasis SVG dan seharusnya lebih baik dalam merender animasi . Namun, saya ragu seberapa jauh lebih baik dan apa plafon kinerjanya. Untuk alasan itu, saya juga mempertimbangkan perombakan yang lebih lengkap menggunakan pustaka berbasis kanvas seperti KineticJS . Namun, sebelum saya terlalu jauh menggunakan satu pendekatan atau lainnya, saya ingin mendengar dari seseorang yang telah melakukan aplikasi web serupa dengan banyak data dan mendapatkan pendapat mereka.

Hal terpenting adalah kinerja, dengan fokus kedua pada kemudahan menambahkan fitur interaksi lain dan memprogram animasi. Mungkin tidak akan ada lebih dari 2000 titik sekaligus, dengan bilah kesalahan kecil di masing-masing titik. Memperbesar, memperkecil, dan menggeser harus dilakukan dengan mulus. Jika pustaka SVG terbaru layak dalam hal ini, maka mungkin kemudahan menggunakan d3 akan lebih besar daripada peningkatan penyiapan untuk KineticJS, dll. Tetapi jika ada keuntungan kinerja yang sangat besar untuk menggunakan kanvas, terutama untuk orang dengan komputer yang lebih lambat, maka saya pasti lebih suka pergi ke sana.

Contoh aplikasi yang dibuat oleh NYTimes yang menggunakan SVG, tetapi animasi masih dapat diterima dengan lancar: http://www.nytimes.com/interactive/2012/05/17/business/dealbook/how-the-facebook-offering-compares.html . Jika saya bisa mendapatkan kinerja itu dan tidak harus menulis kode gambar kanvas saya sendiri, saya mungkin akan memilih SVG.

Saya perhatikan bahwa beberapa pengguna telah menggunakan hibrida manipulasi d3.js yang dikombinasikan dengan rendering kanvas . Namun, saya tidak dapat menemukan banyak dokumentasi tentang ini secara online atau menghubungi OP dari posting itu. Jika ada yang memiliki pengalaman melakukan implementasi DOM-ke-Kanvas ( demo , kode ) semacam ini , saya ingin mendengar dari Anda juga. Tampaknya ini adalah kombinasi yang baik untuk dapat memanipulasi data dan memiliki kontrol khusus atas cara merendernya (dan karena itu kinerja), tetapi saya bertanya-tanya apakah harus memuat semuanya ke DOM masih akan memperlambat segalanya.

Saya tahu bahwa ada beberapa pertanyaan yang mirip dengan pertanyaan ini, tetapi tidak satupun dari mereka menanyakan hal yang sama. Terima kasih atas bantuan Anda.

Tindak lanjut : implementasi yang akhirnya saya gunakan ada di https://github.com/zooniverse/LightCurves

Andrew Mao
sumber
"Yang paling penting adalah kinerja, dengan fokus kedua pada kemudahan menambahkan interaksi lain" +1 untuk kanvas
philipp
Pertanyaannya adalah, apakah SVG cukup di sebagian besar browser untuk 2k poin + elemen bagan lainnya? Jika demikian, dan kelambatan hanya karena kelemahan dalam protovis, maka saya lebih suka tetap menggunakan SVG.
Andrew Mao
1
Mike Bostock telah memberikan jawaban yang bagus. Untuk beberapa info tambahan, Anda dapat melihat dua sumber berikut: stackoverflow.com/questions/5882716/html5-canvas-vs-svg-vs-div/… blogs.msdn.com/b/ie/archive/2011/04/22 /…
Ümit
8
Tindak lanjut: Saya telah menerapkan ini dengan pendekatan SVG / kanvas hibrid, di mana SVG menangani sumbu dan garis kisi dan kanvas dapat merender titik-titik dengan sangat cepat. Ini sangat cepat!
Andrew Mao

Jawaban:

183

Untungnya, menggambar 2000 lingkaran adalah contoh yang cukup mudah untuk diuji. Jadi, inilah empat kemungkinan implementasi, masing-masing dua Canvas dan SVG:

Contoh ini menggunakan perilaku zoom D3 untuk menerapkan zooming dan panning. Selain dari apakah lingkaran dirender dalam Canvas atau SVG, perbedaan utama lainnya adalah apakah Anda menggunakan zoom geometris atau semantik .

Zoom geometris berarti Anda menerapkan satu transformasi ke seluruh area pandang: saat Anda memperbesar, lingkaran menjadi lebih besar. Perbesaran semantik kontras berarti Anda menerapkan transformasi ke setiap lingkaran secara individual: saat Anda memperbesar, lingkaran tetap berukuran sama tetapi menyebar. Planethunters.org saat ini menggunakan pembesaran semantik, tetapi mungkin berguna untuk mempertimbangkan kasus lain.

Zoom geometris menyederhanakan implementasi: Anda menerapkan terjemahan dan skala sekali, lalu semua lingkaran ditampilkan ulang. Penerapan SVG sangat sederhana, memperbarui atribut "transform" tunggal. Performa kedua contoh pembesaran geometris terasa lebih dari cukup. Untuk pembesaran semantik, Anda akan melihat bahwa D3 secara signifikan lebih cepat daripada Protovis. Ini karena ia melakukan pekerjaan yang jauh lebih sedikit untuk setiap acara zoom. (Versi Protovis harus menghitung ulang semua atribut pada semua elemen.) Pembesaran semantik berbasis kanvas sedikit lebih lincah daripada SVG, tetapi pembesaran semantik SVG masih terasa responsif.

Namun tidak ada peluru ajaib untuk kinerja, dan empat kemungkinan pendekatan ini tidak mulai mencakup seluruh kemungkinan. Misalnya, Anda dapat menggabungkan zoom geometris dan semantik, menggunakan pendekatan geometris untuk menggeser (memperbarui atribut "transform") dan hanya menggambar ulang lingkaran individu saat melakukan zoom. Anda bahkan mungkin dapat menggabungkan satu atau beberapa teknik ini dengan transformasi CSS3 untuk menambahkan beberapa akselerasi perangkat keras (seperti dalam contoh bundling tepi hierarkis ), meskipun itu bisa sulit untuk diterapkan dan mungkin memperkenalkan artefak visual.

Namun, preferensi pribadi saya adalah menyimpan sebanyak mungkin dalam SVG, dan menggunakan Canvas hanya untuk "lingkaran dalam" saat rendering menjadi hambatan . SVG memiliki begitu banyak kemudahan untuk pengembangan — seperti CSS, data-joins, dan pemeriksa elemen — sehingga sering kali pengoptimalan prematur untuk memulai dengan Canvas. Menggabungkan Canvas dengan SVG, seperti dalam visualisasi IPO Facebook yang Anda tautkan, adalah cara yang fleksibel untuk mempertahankan sebagian besar kemudahan ini sambil tetap menghasilkan kinerja terbaik. Saya juga menggunakan teknik ini di Cubism.js , di mana kasus khusus dari visualisasi deret waktu cocok untuk cache bitmap.

Seperti yang ditunjukkan contoh berikut, Anda dapat menggunakan D3 dengan Canvas, meskipun bagian dari D3 spesifik untuk SVG. Lihat juga grafik gaya-gaya dan contoh deteksi tabrakan ini .

mbostock.dll
sumber
Wow, itu jawaban yang luar biasa, dan dari ahli visualisasi sendiri! Saya pikir saya harus tetap menggunakan pembesaran semantik, dan di komputer saya, perender berbasis kanvas jauh lebih cepat daripada versi SVG saat melakukan panning / zooming (mungkin ada hubungannya dengan implementasi browser?). Apa yang Anda katakan tentang menggunakan SVG dengan kanvas sebagai loop dalam persis seperti yang ingin saya konfirmasikan, dan contoh kodenya hanyalah bonus manis. Terima kasih banyak!
Andrew Mao
Baru saja terpikir untuk mencoba contoh zoom semantik pada browser yang berbeda: Chrome, keduanya cukup cepat, saya tidak bisa membedakannya; YAITU: SVG sedikit lebih lambat; Firefox (komentar terakhir): SVG sangat lambat dibandingkan dengan kanvas. Saya rasa itu juga sedikit memperumit keputusan, tetapi membuat rendering kanvas menjadi pilihan yang aman. Satu pertanyaan lagi: Apakah menggunakan KineticJS sebagai ganti kanvas secara langsung akan memengaruhi kinerja secara signifikan?
Andrew Mao
1
Andrew, sedikit terlambat tapi inilah pengalaman saya dengan FF: Mengejar. Saya biasa menjalankan transisi FF 15 dan D3 SVG dengan cepat mulai menjadi lambat. Tetapi setiap versi baru menjadi jauh lebih cepat. Sekarang saya menggunakan FF 18 beta dan itu cepat dibandingkan dengan 17. Tidak yakin apakah itu sehalus chrome sekalipun.
user2503795
@AndrewMao Hai Andrew, saya mengalami situasi di mana rendering tampaknya menjadi penghambat. Saya perlu menggeser dan memperbesar beberapa titik dan sekitar 6000 jalur kurva. stackoverflow.com/questions/17907769/svg-path-rendering-speed/… Tapi saya tidak begitu mengerti Bostock ketika dia berkata "simpan sebanyak mungkin di SVG, dan gunakan Canvas hanya untuk" lingkaran dalam "" Saya punya melihat keempat contoh itu .. Bisakah Anda memberi penjelasan?
kakacii
@kakacii adalah transformasi yang sama lambatnya di semua browser? Jika demikian, saya akan mengatakan Anda menggunakan kode yang salah atau Anda telah mencapai batas rendering browser. Jika Anda dapat memposting beberapa kode, saya mungkin dapat membantu. mbostock mengacu pada penggunaan SVG untuk kesederhanaan manipulasi dan kanvas hanya seperlunya karena lebih rumit untuk membuat kode. Namun perpustakaan seperti KineticJS sampai batas tertentu telah menyederhanakannya.
Andrew Mao
8

Saya pikir dalam kasus Anda keputusan antara kanvas dan svg bukanlah seperti keputusan antara »menunggang kuda« atau mengendarai »Porsche«. Bagi saya ini lebih seperti keputusan tentang warna mobil.

Izinkan saya menjelaskan: Dengan asumsi bahwa, berdasarkan kerangka kerja operasi

  • menggambar bintang,
  • tambahkan bintang dan
  • hapus bintang

ambil waktu linier. Jadi, jika keputusan kerangka kerja Anda bagus, itu akan sedikit lebih cepat, jika tidak, sedikit lebih lambat.

Jika Anda terus berasumsi bahwa kerangka kerja hanya cepat, daripada menjadi sangat jelas bahwa kurangnya kinerja disebabkan oleh jumlah bintang yang tinggi dan menanganinya adalah sesuatu yang tidak dapat dilakukan kerangka kerja untuk Anda, setidaknya saya tidak tahu tentang ini.

Yang ingin saya sampaikan adalah bahwa dasar dari masalah tersebut mengarah pada masalah dasar dari komputasi geometri, yaitu: pencarian jarak dan satu lagi grafik komputer: tingkat detail .

Untuk mengatasi masalah kinerja Anda, Anda perlu menerapkan praprosesor yang baik yang dapat dengan cepat menemukan bintang mana yang akan ditampilkan dan mungkin dapat mengelompokkan bintang yang berdekatan, tergantung pada zoom. Satu-satunya hal yang membuat tampilan Anda jelas dan cepat adalah menjaga jumlah bintang yang akan digambar serendah mungkin.

Seperti yang Anda nyatakan, yang paling penting adalah kinerja, daripada saya cenderung menggunakan kanvas, karena ini berfungsi tanpa operasi DOM. Ini juga menawarkan kesempatan untuk menggunakan webGL, yang sangat meningkatkan kinerja grafis.

BTW: apakah Anda memeriksa paper.js ? Ini menggunakan kanvas, tetapi mengemulasi grafik vektor.

PS: Di Buku ini Anda dapat menemukan pembahasan yang sangat rinci tentang grafik di web, teknologi, pro dan kontra kanvas, SVG dan DHTML.

philipp
sumber
7

Saya baru-baru ini mengerjakan dasbor yang hampir realtime (menyegarkan setiap 5 detik) dan memilih untuk menggunakan grafik yang dirender menggunakan kanvas.

Kami mencoba Highcharts (library JavaScript Charting berbasis SVG) dan CanvasJS (library JavaScript Charting berbasis Canvas). Meskipun Highcharts adalah API bagan yang fantastis dan menawarkan lebih banyak fitur, kami memutuskan untuk menggunakan CanvasJS.

Kami perlu menampilkan setidaknya 15 menit data per grafik (dengan opsi untuk memilih rentang maksimal dua jam).

Jadi selama 15 menit: 900 poin (titik data per detik) x2 (grafik kombinasi garis dan batang) grafik x4 = total 7200 poin.

Menggunakan chrome profiler, dengan CanvasJS, memori tidak pernah melebihi 30MB sementara dengan penggunaan memori Highcharts melebihi 600MB.

Juga dengan waktu refresh 5 detik rendering CanvasJS dibagikan lebih responsif daripada Highcharts.

Kami menggunakan satu timer (setInterval 5 detik) untuk membuat 4 panggilan REST API untuk mengambil data dari server back end yang terhubung ke Elasticsearch. Setiap bagan diperbarui saat data diterima oleh JQuery.post ().

Yang mengatakan untuk laporan offline saya akan menggunakan Highcharts karena API-nya yang lebih fleksibel.

Ada juga bagan Zing yang mengklaim menggunakan SVG atau Canvas tetapi belum melihatnya.

Kanvas harus dipertimbangkan ketika kinerja sangat penting. SVG untuk fleksibilitas. Bukan berarti kerangka kanvas tidak fleksibel, tetapi dibutuhkan lebih banyak pekerjaan untuk kerangka kanvas untuk mendapatkan fungsionalitas yang sama dengan kerangka kerja svg.

pengguna432024
sumber
3

Mungkin juga melihat Bagan Meteor, yang dibangun di atas kerangka KineticJS yang sangat cepat: http://meteorcharts.com/

Eric Rowell
sumber
0

Saya juga menemukan ketika kita mencetak ke PDF halaman dengan grafik SVG, PDF yang dihasilkan masih berisi gambar berbasis vektor, sedangkan jika Anda mencetak halaman dengan grafik Canvas, gambar di file PDF yang dihasilkan akan di-raster.

ostrokach.dll
sumber