2010-06-09 3 views
140

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

Donc, si je fais un clearRect sur la couche supérieure, il ne sera pas effacer celle du bas?

Merci.

+1

vérifier cela .. http://html5.litten.com/using-multiple-html5-canvas-as-layers/ cela vous aidera à résoudre votre problème de manière correcte – Dakshika

+0

vous pouvez jeter un oeil à http://radikalfx.com/2009/10/16/canvas-collage/. il utilise une sorte de technique de "couches". – Matthew

Répondre

214

Non, mais vous pouvez superposer plusieurs éléments <canvas> sur le dessus de l'autre et d'accomplir quelque chose de similaire.

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

Dessine ta première couche sur la toile layer1, et la deuxième couche sur la toile layer2. Ensuite, quand vous clearRect sur le calque du haut, tout ce qui est sur la toile inférieure montrera à travers.

+3

Merci pour votre réponse. Un bemol: z-index pas zIndex;) – Gregoire

+0

Merci, mis à jour. – jimr

+0

est-il un moyen de cacher/afficher une couche .. de telle sorte que je peux cacher layer1 et afficher layer2 et faire vice-versa si nécessaire .. ?? – Zaraki

26

associés à ceci:

Si vous avez quelque chose sur votre toile et que vous voulez dessiner quelque chose à l'arrière de celui-ci - vous pouvez le faire en modifiant le réglage de context.globalCompositeOperation à « destination-over » - et puis retournez-le à "source-over" lorsque vous avez terminé.

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

Vous pouvez créer plusieurs canvas éléments sans les annexant dans le document. Ceux-ci seront vos couches:

faire alors tout ce que vous voulez avec eux et à la fin tout simplement rendre leur contenu en ordre sur toile de destination en utilisant drawImage sur context.

+0

Performance tueur. Environ ~ 10 fois plus lent. – SCLeo

+2

@SCLeo vous avez dit "Performance killer. ~ 10 fois plus lent" est complètement faux. Selon les cas d'utilisation en utilisant une seule toile DOM et en rendant les canevas hors écran à cela, il est plus rapide que l'empilement de canevas dans DOM. L'erreur courante est de rendre les appels de rendu de référence, les appels de dessin de toile peuvent être chronométrés, le rendu de DOM est en dehors du contexte de Javascripts et ne peut pas être chronométré. Le résultat est que la toile empilée be DOM n'obtient pas le rendu de composition (fait par DOM) inclus dans le benchmark .. – Blindman67

+0

@ Blindman67 Je sais ce que tu veux dire. Il suffit de commander ce cas-test: https://jsfiddle.net/9a9L8k7k/1/. Au cas où vous vous méprenez, il y a trois toiles, toile 1 (ctx1) est une vraie toile. Canvas 2 (ctx2) et canvas 3 (ctx) sont hors écran. L'image a été précédemment rendue sur ctx3. Dans le test 1 de ce benchmark, je rends directement ctx3 sur ctx1. Dans le test 2, je rends ctx3 sur ctx2 puis ctx2 sur ctx1. Le test 2 est 30 fois plus lent que le test 1 sur mon ordinateur. C'est pourquoi je dis que l'utilisation d'une toile intermédiaire est beaucoup plus lente. – SCLeo

4

j'avais trop ce même problème, je en plusieurs éléments en toile avec position: absolute fait le travail, si vous voulez enregistrer la sortie dans une image, qui ne va pas au travail. Je suis donc allé de l'avant et j'ai fait un simple "système" de codage comme si chaque couche avait son propre code, mais tout est rendu dans le même élément.

https://github.com/federicojacobi/layeredCanvas

Je compte d'ajouter des fonctionnalités supplémentaires, mais il le fera maintenant.

Vous pouvez faire plusieurs fonctions et les appeler pour les couches « faux ».

+0

Celui-ci est parfait. – Nadir

2

Vous pouvez également consulter le http://www.concretejs.com qui est un cadre en toile Html5 moderne et léger qui permet la détection de coupures, la superposition et bien d'autres choses périphériques. Vous pouvez faire des choses comme ceci:

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

vraiment apprécier votre travail – Guigui

0

Je comprends que le Q ne veut pas utiliser une bibliothèque, mais je vais offrir ce pour d'autres provenant de recherches Google. @EricRowell a mentionné un bon plugin, mais, il y a aussi un autre plugin que vous pouvez essayer, html2canvas.

Dans notre cas, nous utilisons des PNG transparents en couches avec z-index en tant que widget «Product Builder». Html2canvas a travaillé avec brio pour faire bouillir la pile sans pousser les images, ni utiliser les complexités, les solutions de contournement et la toile "non-réactive" elle-même. Nous n'avons pas été en mesure de le faire en douceur/sane avec le canvas vanilla + JS.

D'abord, utilisez z-index sur les divs absolus pour générer du contenu en couches dans un wrapper positionné relatif. Ensuite, placez le wrapper dans html2canvas pour obtenir un canevas rendu, que vous pouvez laisser tel quel, ou en sortie en tant qu'image afin qu'un client puisse l'enregistrer.

+0

Si vous avez des images plus lourdes, cela prendra un certain temps pour convertir du HTML en toile, nous avons dû nous éloigner de ce juste parce que le rendu a pris du temps. – Vilius

+0

@Vilius ouais bon appel sur les images lourdes/grandes. Nous avons essayé de coller à 300K images ou moins avec pas plus de 4 couches, sinon les clients victimes de ressources sentiraient la brûlure lors du téléchargement de l'image compostée finale. Curieux, qu'avez-vous décidé de faire pour réduire ce temps? – dhaupin

+0

Eh bien, nous avons fait une grosse erreur en utilisant des éléments html pour dessiner quelque chose en premier lieu. Parce que notre api a renvoyé x, y, width et height, nous avons déplacé jscanavs pour dessiner l'image au lieu d'utiliser des éléments html. Rappelez-vous que nous avons eu quelques problèmes avec la rotation (les points de départ étaient un peu gênants et imprévisibles) et que nous avons appliqué des images en utilisant des dimensions spécifiques, mais tout a finalement été résolu. Nous avons également constaté que notre application de traitement d'images drainait beaucoup de ressources, nous avons donc déménagé loin de cela aussi. – Vilius