html5 - tuval öğesi - Birden çok katman


176

Herhangi bir uzantı kütüphanesi olmadan, aynı tuval öğesinde birden çok katman olması mümkün müdür?

Üst katmanda bir clearRect yaparsam, alt katmanı silmez mi?

Teşekkürler.


radikalfx.com/2009/10/16/canvas-collage adresine göz atmak isteyebilirsiniz . bir çeşit "katman" tekniği kullanıyor.
Matthew

2
Bu out .. html5.litten.com/using-multiple-html5-canvases-as-layers bu doğru bir şekilde sorunu çözmek için yardımcı olacaktır
Dakshika

@Dakshika Bu bağlantı için teşekkür ederim, birkaç yıl önce tuvali kullanmamın bir kütüphanenin benim için hallettiği bir sorunu açıkladı.
Fering

Yanıtlar:


267

Hayır, ancak birden çok <canvas>öğeyi üst üste katmanlayabilir ve benzer bir şey başarabilirsiniz.

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

İlk katmanınızı layer1tuval üzerine, ikinci katmanınızı tuval üzerine çizin layer2. Daha sonra clearRectüst katmandayken, alt tuvalde ne varsa görünecektir.


bir katman gizleme / gizleme bir yolu var .. öyle ki ben layer1 gizlemek ve layer2 göstermek ve gerektiğinde tersini yapmak .. ??
Zaraki

4
CSS ile gizleyebilirsiniz - yani display: none;. Ya da sadece tuval gösterilmesi gerektiğinde yeniden çizmek çok pahalı değilse, tuvali temizleyin.
jimr

'Sol' ve 'üst' e atanan değerlerin '0' değil, '0px' olması gerekir.
Bryan Green

6
@BryanGreen Doğru değil. "Bununla birlikte, sıfır uzunluklar için birim tanımlayıcı isteğe bağlıdır (yani, sözdizimsel olarak <sayı> 0 olarak temsil edilebilir)." w3.org/TR/css3-values/#lengths
xehpuk

Birden çok tuval için kompozisyon türünü kontrol edebilir miyim?
19:26

40

Bununla ilgili:

Tuvalinizde bir şey varsa ve arkasına bir şey çizmek istiyorsanız - context.globalCompositeOperation ayarını 'hedef üzerinden' olarak değiştirerek yapabilirsiniz - ve sonra 'kaynak üzerinden' yeniden yapılır.

   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" />


Evet, sorun değil, silme durumunda. bu her iki katmanı paralel olarak silecektir. ki bu yine doğru değil.
Pardeep Jain

27

Birden fazla canvasöğeyi belgeye eklemeden oluşturabilirsiniz . Bunlar katmanlarınız olacak :

O zaman onlara istiyorum ve sonunda sadece kullanılarak hedef tuval en uygun sırayla içeriklerini işlemek ne gerekiyorsa drawImageüzerinde context.

Misal:

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

İşte kod kodları: https://codepen.io/anon/pen/mQWMMW


4
@SCLeo "Performans katili. Yaklaşık ~ 10 kat daha yavaş" dediniz. Kullanım durumlarına bağlı olarak, tek bir DOM tuvali kullanma ve ekran dışı tuvalleri oluşturma, DOM'da tuvali yığınlamaktan daha hızlıdır. Sık karşılaşılan hata, oluşturma çağrılarını kıyaslamak, tuval çizim çağrıları zamanlanabilir, DOM oluşturma Javascripts bağlamının dışındadır ve zamanlanamaz. Sonuç olarak DOM yığılmış tuval olmak kıyaslama (DOM tarafından yapılan) karşılaştırma render almazsınız ..
Blindman67

@ Blindman67 Ne demek istediğini biliyorum. Bu kıstasa göz atın : jsfiddle.net/9a9L8k7k/1 . Yanlış anlamanız durumunda, üç tuval var, tuval 1 (ctx1) gerçek bir tuval. Tuval 2 (ctx2) ve tuval 3 (ctx) ekran dışında. Görüntü daha önce ctx3 üzerine konulmuştur. Bu karşılaştırmalı değerlendirmenin 1. testinde, ctx3'ü doğrudan ctx1 üzerine işlerim. Test 2'de, ctx2 üzerine ctx3 ve sonra ctx2 ila ctx1 oluştururum. Test 2, bilgisayarımdaki test 1'den 30 kat daha yavaş. Bu yüzden ara tuval kullanmanın çok daha yavaş olduğunu söylüyorum.
SCLeo

@ Blindman67 Ekran dışı tuvalin numarası yalnızca ekran dışı tuval statik olduğunda çalışır. Dinamik tuvaller kullanmak performansa büyük zarar verecektir. (Yine söylemeye çalıştığım şey, dinamik ekran dışı tuvalin son derece yavaş olması, bu nedenle muhtemelen bu tekniğin (çoklu ekran dışı tuval tarafından sahte katmanlar) istenmeyeceği)
SCLeo

@ Blindman67 ÖNEMLİ: Kıyaslamanın adresi https://jsfiddle.net/9a9L8k7k/3 , Düzenledikten sonra kaydetmeyi unutuyorum ve Yığın Taşması önceki yorumu değiştirmeme izin vermiyor ...
SCLeo

4
@ Blindman67 Üzgünüm, bu benim hatam. Birden fazla ekran dışı tuval kullanmanın çok düzgün çalıştığını test ettim ve buldum. Bu karşılaştırmanın neden ekran dışı tuval kullanımının bu kadar yavaş olduğunu gösterdiğinden hala emin değilim.
SCLeo

6

Ben de aynı sorunu yaşıyordum, ben pozisyon ile birden fazla tuval elemanları iken: mutlak işi yapar, eğer bir görüntüye çıktı kaydetmek istiyorsanız, bu işe yaramaz.

Bu yüzden devam ettim ve her katmanın kendi kodu varmış gibi kodlamak için basit bir katmanlama "sistemi" yaptım, ancak hepsi aynı öğeye dönüştürülüyor.

https://github.com/federicojacobi/layeredCanvas

Ekstra yetenekler eklemeyi planlıyorum, ama şimdilik yapacak.

Katmanları "sahte" yapmak için birden fazla işlev yapabilir ve bunları çağırabilirsiniz.


Bu mükemmel.
Nadir

4

Ayrıca , isabet algılama, katmanlama ve diğer birçok çevresel şeyi sağlayan modern, hafif, Html5 tuval çerçevesi olan http://www.concretejs.com adresine de göz atabilirsiniz. Bunun gibi şeyler yapabilirsiniz:

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

Bu katmanlar hangi şekilde DOM'da sonuçlanacak? Her birine CSS üzerinden erişilebiliyor mu?
Garavani

0

Q'nun bir kütüphane kullanmak istemediğini anlıyorum, ancak bunu Google aramalarından gelen diğerleri için sunacağım. @EricRowell iyi bir eklentiden bahsetti, ancak deneyebileceğiniz başka bir eklenti daha var, html2canvas .

Bizim durumumuzda, z-index"ürün oluşturucu" widget olarak katmanlı şeffaf PNG'ler kullanıyoruz . Html2canvas, görüntüleri itmeden veya karmaşıklıkları, geçici çözümleri ve "yanıt vermeyen" tuvali kullanmadan yığını kaynatmak için mükemmel bir şekilde çalıştı. Bunu vanilya tuvali + JS ile sorunsuz / aklı başında yapamadık.

z-indexGöreli konumlandırılmış bir paket içinde katmanlı içerik oluşturmak için mutlak div'larda ilk kullanım . Ardından, olduğu gibi bırakabileceğiniz veya bir istemcinin kaydedebilmesi için bir görüntü olarak çıkabileceğiniz işlenmiş bir tuval elde etmek için sargıyı html2canvas ile borulayın.


Daha ağır resimleriniz varsa, HTML'yi tuvale dönüştürmek biraz zaman alacaktır, çünkü oluşturma işlemi uzun sürdüğü için bundan uzaklaşmak zorunda kaldık.
Vilius

@Vilius evet ağır / büyük görüntüler iyi bir çağrı. 4 kattan fazla olmayan 300K veya daha az görüntüye sadık kalmaya çalıştık, aksi takdirde kaynak dar istemciler son kompost görüntüyü indirirken yanık hissedeceklerdi. Merakla, bu azaltılmış zamana ne geçtiniz?
dhaupin

İlk etapta bir şey çizmek için html elemanlarını kullanarak büyük bir hata yaptık. API'miz x, y, width ve height döndürdüğünden, html öğeleri kullanmak yerine resmi çizmek için jscanavs'a taşındık. Döndürme (başlangıç ​​noktaları biraz garip ve öngörülemezdi) ve belirli boyutlar kullanarak görüntüler uygulayarak birkaç sorun yaşadığımızı unutmayın, ancak hepsi sonunda çözüldü. Ayrıca, görüntü işleme uygulamamızın çok fazla kaynak tükettiğini gördük, bu yüzden de bundan uzaklaştık.
Vilius

0

ancak katman 02, katman 01'deki tüm çizimleri kapsayacaktır. Bunu her iki katmandaki çizimi göstermek için kullandım. (arka plan rengi: şeffaf;) tarzında kullanın.

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.