html5 - elemen kanvas - Beberapa lapisan

176

Tanpa pustaka ekstensi, mungkinkah memiliki beberapa lapisan dalam elemen kanvas yang sama?

Jadi jika saya melakukan clearRect pada lapisan atas, itu tidak akan menghapus yang bawah?

Terima kasih.

Gregoire
sumber
Anda mungkin ingin melihat radikalfx.com/2009/10/16/canvas-collage . dia menggunakan semacam teknik "lapisan".
Matius
2
lihat ini .. html5.litten.com/using-multiple-html5-canvases-as-layers ini akan membantu Anda untuk menyelesaikan masalah Anda dengan cara yang tepat
Dakshika
@Dakshika Terima kasih atas tautannya, itu menjelaskan masalah saya telah menggunakan kanvas beberapa tahun yang lalu bahwa perpustakaan merawat saya.
Fering

Jawaban:

267

Tidak, bagaimanapun, Anda dapat melapisi banyak <canvas>elemen di atas satu sama lain dan mencapai sesuatu yang serupa.

<div style="position: relative;">
 <canvas id="layer1" width="100" height="100" 
   style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
 <canvas id="layer2" width="100" height="100" 
   style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
</div>

Gambarlah lapisan pertama Anda di layer1kanvas, dan lapisan kedua di layer2kanvas. Kemudian ketika Anda clearRectberada di lapisan atas, apa pun yang ada di kanvas bawah akan terlihat.

jimr
sumber
apakah ada cara untuk menyembunyikan / menyembunyikan lapisan .. sedemikian rupa sehingga saya bisa menyembunyikan layer1 dan menunjukkan layer2 dan melakukan sebaliknya ketika diperlukan .. ??
Zaraki
4
Anda bisa menyembunyikannya dengan CSS - yaitu display: none;. Atau cukup bersihkan kanvas, jika tidak super mahal untuk menggambar ulang lagi ketika layer harus ditampilkan.
jimr
Nilai yang ditetapkan ke 'kiri' dan 'atas' harus '0px', bukan '0'.
Bryan Green
6
@ BryanGreen Tidak benar. "Namun, untuk panjang nol, pengidentifikasi unit adalah opsional (yaitu dapat secara sintaksis direpresentasikan sebagai <number> 0)." w3.org/TR/css3-values/#lengths
xehpuk
Bisakah saya mengontrol jenis komposisi untuk beberapa kanvas?
ziyuang
40

Terkait dengan ini:

Jika Anda memiliki sesuatu di kanvas dan ingin menggambar sesuatu di belakangnya - Anda dapat melakukannya dengan mengubah konteks.globalCompositeOperasi pengaturan ke 'tujuan-lebih' - dan kemudian mengembalikannya ke 'sumber-lebih' ketika Anda ' sudah selesai.

   var context = document.getElementById('cvs').getContext('2d');

    // Draw a red square
    context.fillStyle = 'red';
    context.fillRect(50,50,100,100);



    // Change the globalCompositeOperation to destination-over so that anything
    // that is drawn on to the canvas from this point on is drawn at the back
    // of what's already on the canvas
    context.globalCompositeOperation = 'destination-over';



    // Draw a big yellow rectangle
    context.fillStyle = 'yellow';
    context.fillRect(0,0,600,250);


    // Now return the globalCompositeOperation to source-over and draw a
    // blue rectangle
    context.globalCompositeOperation = 'source-over';

    // Draw a blue rectangle
    context.fillStyle = 'blue';
    context.fillRect(75,75,100,100);
<canvas id="cvs" />

Richard
sumber
ya, itu baik-baik saja tetapi dalam kasus penghapusan, seperti yang ditanyakan. ini akan menghapus kedua lapisan secara paralel. yang lagi tidak benar.
Pardeep Jain
27

Anda dapat membuat banyak canvaselemen tanpa menambahkannya ke dalam dokumen. Ini akan menjadi layer Anda :

Kemudian melakukan apapun yang Anda inginkan dengan mereka dan pada akhirnya hanya membuat konten mereka dalam urutan yang benar di kanvas tujuan menggunakan drawImagedi context.

Contoh:

/* using canvas from DOM */
var domCanvas = document.getElementById('some-canvas');
var domContext = domCanvas.getContext('2d');
domContext.fillRect(50,50,150,50);

/* virtual canvase 1 - not appended to the DOM */
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = 'blue';
ctx.fillRect(50,50,150,150);

/* virtual canvase 2 - not appended to the DOM */    
var canvas2 = document.createElement('canvas')
var ctx2 = canvas2.getContext('2d');
ctx2.fillStyle = 'yellow';
ctx2.fillRect(50,50,100,50)

/* render virtual canvases on DOM canvas */
domContext.drawImage(canvas, 0, 0, 200, 200);
domContext.drawImage(canvas2, 0, 0, 200, 200);

Dan inilah beberapa codepen: https://codepen.io/anon/pen/mQWMMW

juszczak
sumber
4
@SCLeo Anda mengatakan "Pembunuh kinerja. Tentang ~ 10 kali lebih lambat" benar-benar salah. Tergantung pada kasus penggunaan menggunakan kanvas DOM tunggal dan rendering kanvas offscreen yang lebih cepat daripada menumpuk kanvas di DOM. Kesalahan umum adalah pembandingan panggilan rendering, panggilan draw kanvas dapat diatur waktunya, rendering DOM berada di luar konteks Javascripts dan tidak dapat ditentukan waktunya. Hasilnya adalah bahwa kanvas DOM yang ditumpuk tidak mendapatkan rendering pengomposisian (dilakukan oleh DOM) yang termasuk dalam patokan ..
Blindman67
@ Blindman67 Saya tahu maksud Anda. Cek saja patokan ini: jsfiddle.net/9a9L8k7k/1 . Jika Anda salah paham, ada tiga kanvas, kanvas 1 (ctx1) adalah kanvas asli. Kanvas 2 (ctx2) dan kanvas 3 (ctx) tidak aktif. Gambar sebelumnya telah dirender ke ctx3. Dalam pengujian 1 dari tolok ukur ini, saya langsung merender ctx3 ke ctx1. Dalam tes 2, saya merender ctx3 ke ctx2 dan kemudian ctx2 ke ctx1. Tes 2 adalah 30 kali lebih lambat dari tes 1 di komputer saya. Itu sebabnya saya katakan menggunakan kanvas perantara jauh lebih lambat.
SCLeo
@ Blindman67 Trik kanvas di luar layar hanya berfungsi ketika kanvas di luar layar itu statis. Menggunakan kanvas yang dinamis akan sangat merusak kinerja. (Sekali lagi, apa yang ingin saya katakan adalah bahwa kanvas di luar layar yang dinamis sangat lambat sehingga mungkin teknik ini (lapisan tiruan oleh beberapa kanvas di luar layar) tidak akan diinginkan)
SCLeo
@ Blindman67 PENTING: Alamat benchmark adalah https://jsfiddle.net/9a9L8k7k/3 , saya lupa menyimpan setelah mengedit dan Stack Overflow tidak membiarkan saya mengubah komentar sebelumnya lagi ...
SCLeo
4
@ Blindman67 Maaf, ini kesalahan saya. Saya menguji dan menemukan bahwa menggunakan beberapa kanvas layar off berjalan sangat lancar. Saya masih tidak yakin mengapa tolok ukur itu menunjukkan bahwa menggunakan kanvas dari layar adalah yang lambat.
SCLeo
6

Saya juga mengalami masalah yang sama, saya sementara beberapa elemen kanvas dengan posisi: absolut melakukan pekerjaan, jika Anda ingin menyimpan output ke dalam gambar, itu tidak akan berhasil.

Jadi saya pergi ke depan dan melakukan layering "sistem" sederhana untuk mengkodekan seolah-olah setiap lapisan memiliki kode sendiri, tetapi semuanya akan dirender ke dalam elemen yang sama.

https://github.com/federicojacobi/layeredCanvas

Saya berniat untuk menambah kemampuan tambahan, tetapi untuk sekarang ini akan berhasil.

Anda dapat melakukan banyak fungsi dan memanggilnya untuk lapisan "palsu".

Federico Jacobi
sumber
Yang ini sempurna.
Nadir
4

Anda mungkin juga checkout http://www.concretejs.com yang merupakan kerangka kanvas Html5 modern, ringan yang memungkinkan deteksi hit, layering, dan banyak hal periferal lainnya. Anda dapat melakukan hal-hal seperti ini:

var wrapper = new Concrete.Wrapper({
  width: 500,
  height: 300,
  container: el
});

var layer1 = new Concrete.Layer();
var layer2 = new Concrete.Layer();

wrapper.add(layer1).add(layer2);

// draw stuff
layer1.sceneCanvas.context.fillStyle = 'red';
layer1.sceneCanvas.context.fillRect(0, 0, 100, 100);

// reorder layers
layer1.moveUp();

// destroy a layer
layer1.destroy();
Eric Rowell
sumber
Dengan cara apa lapisan-lapisan itu akan berakhir di DOM? Masing-masing dapat diakses melalui CSS?
Garavani
0

Saya mengerti bahwa Q tidak ingin menggunakan perpustakaan, tetapi saya akan menawarkan ini untuk orang lain yang berasal dari pencarian Google. @EricRowell menyebutkan plugin yang bagus, tapi, ada juga plugin lain yang bisa Anda coba, html2canvas .

Dalam kasus kami, kami menggunakan z-indexwidget PNG berlapis transparan dengan sebagai "pembangun produk". Html2canvas bekerja dengan cemerlang untuk merebus tumpukan tanpa mendorong gambar, atau menggunakan kompleksitas, solusi, dan kanvas "non-responsif" itu sendiri. Kami tidak dapat melakukan ini dengan lancar / waras dengan kanvas vanilla + JS.

Pertama digunakan z-indexpada div absolut untuk menghasilkan konten berlapis dalam pembungkus posisi relatif. Kemudian pipa pembungkus melalui html2canvas untuk mendapatkan kanvas yang diberikan, yang dapat Anda biarkan apa adanya, atau output sebagai gambar sehingga klien dapat menyimpannya.

dhaupin
sumber
Jika Anda memiliki gambar yang lebih berat, ini akan membutuhkan waktu untuk mengonversi HTML ke kanvas, kami harus beralih dari ini hanya karena proses renderingnya memakan waktu lama.
Vilius
@Vilius ya panggilan bagus untuk gambar besar / berat. Kami mencoba untuk tetap menggunakan 300 ribu gambar atau kurang dengan tidak lebih dari 4 lapisan, jika tidak, klien yang mengalami kesulitan sumber daya akan merasakan luka bakar ketika mengunduh gambar kompos akhir. Penasaran, apa yang Anda pindahkan ke waktu yang berkurang itu?
dhaupin
Yah, kami membuat kesalahan besar dengan menggunakan elemen html untuk menggambar sesuatu di tempat pertama. Karena api kami mengembalikan x, y, lebar dan tinggi, kami pindah ke jscanavs untuk menggambar gambar daripada menggunakan elemen html. Pikiran Anda, kami memiliki beberapa masalah dengan rotasi (titik awal agak canggung dan tidak dapat diprediksi) dan menerapkan gambar ke sana menggunakan dimensi tertentu tetapi semua akhirnya diselesaikan. Kami juga menemukan bahwa aplikasi pemrosesan gambar kami menguras banyak sumber daya, jadi kami juga beralih dari itu.
Vilius
0

tapi layer 02, akan mencakup semua gambar di layer 01. Saya menggunakan ini untuk menunjukkan gambar di kedua layer. gunakan (warna latar: transparan;) dalam gaya.

    <div style="position: relative;"> 
      <canvas id="lay01" width="500" height="500" style="position: absolute; left: 0; top: 0; z-index: 0; background-color: transparent;">
      </canvas> 
      <canvas id="lay02" width="500" height="500" style="position: absolute; left: 0; top: 0; z-index: 1; background-color: transparent;">
      </canvas>
</div>

aymhenry
sumber