web-dev-qa-db-fra.com

html5 - élément de toile - Plusieurs couches

Sans bibliothèque d'extension, est-il possible d'avoir plusieurs calques dans le même élément de toile?

Donc, si je fais un clearRect sur la couche supérieure, cela n’effacera pas la couche inférieure?

Merci.

163
Gregoire

Non, toutefois, vous pouvez superposer plusieurs <canvas> et superposer des éléments similaires.

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

Dessinez votre premier calque sur le canevas layer1 et le deuxième calque sur le canevas layer2. Ensuite, lorsque vous clearRect sur le calque supérieur, tout ce qui se trouve sur le canevas inférieur sera visible.

247
jimr

Relatif à ceci:

Si vous avez quelque chose sur votre toile et que vous voulez dessiner quelque chose à l'arrière de celle-ci, vous pouvez le faire en modifiant le paramètre context.globalCompositeOperation en 'destination-over' - puis en le remplaçant par 'source-over'. re fait.

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

// Draw a red square

co.fillStyle = 'red';
co.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 whats already on the canvas

co.globalCompositeOperation = 'destination-over';



// Draw a big yellow rectangle

co.fillStyle = 'yellow';
co.fillRect(0,0,600,250);


// Now return the globalCompositeOperation to source-over and draw a
// blue rectangle

co.globalCompositeOperation = 'source-over';

co.fillStyle = 'blue';
co.fillRect(75,75,100,100);
32
Richard

Vous pouvez créer plusieurs éléments canvas sans les ajouter au document. Ce seront vos couches :

Ensuite, faites ce que vous voulez avec eux et, à la fin, restituez leur contenu dans le bon ordre sur le canevas de destination en utilisant drawImage sur context.

Exemple:

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

Et voici un code: https://codepen.io/anon/pen/mQWMMW

23
juszczak

J'avais aussi le même problème, alors que plusieurs éléments de canevas avec position: Absolue fait le travail. Si vous souhaitez enregistrer le résultat dans une image, cela ne fonctionnera pas.

Alors je suis allé de l'avant et j'ai fait un simple "système" de couches pour coder comme si chaque couche avait son propre code, mais tout était rendu dans le même élément.

https://github.com/federicojacobi/layeredCanvas

J'ai l'intention d'ajouter des capacités supplémentaires, mais pour le moment, cela ira.

Vous pouvez effectuer plusieurs fonctions et les appeler afin de "simuler" des calques.

4
Federico Jacobi

Vous pouvez également passer à la caisse http://www.concretejs.com qui est un framework de canevas Html5 moderne et léger, qui permet la détection des hits, la superposition de couches et bien d’autres choses périphériques. Vous pouvez faire des choses comme ça:

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();
3
Eric Rowell

Je comprends que le Q ne souhaite pas utiliser une bibliothèque, mais je proposerai cette option aux autres personnes issues de recherches Google. @EricRowell a mentionné un bon plugin, mais vous pouvez également essayer un autre plugin, html2canvas .

Dans notre cas, nous utilisons des fichiers PNG transparents superposés avec z-index en tant que widget "Générateur de produit". Html2canvas a travaillé avec brio pour réduire l’empilement de pile sans pousser d’images, ni utiliser de complexités, contournements et la toile "non sensible" elle-même. Nous n’avons pas pu le faire en douceur avec la toile Vanilla + JS.

Commencez par utiliser z-index sur des divs absolus pour générer un contenu en couches dans un wrapper positionné de manière relative. Puis dirigez le wrapper dans html2canvas pour obtenir un canevas rendu, que vous pouvez laisser tel quel, ou pour le produire sous forme d'image afin qu'un client puisse l'enregistrer.

0
dhaupin