2010-06-09 20 views
140

Sin ninguna biblioteca de extensión, ¿es posible tener varias capas en el mismo elemento de lienzo?html5 - elemento de lienzo - Varias capas

Entonces, si hago un clearRect en la capa superior, ¿no borrará el de abajo?

Gracias.

+1

mira esto ... http://html5.litten.com/using-multiple-html5-canvases-as-layers/ esto te ayudará a resolver el problema de manera adecuada – Dakshika

+0

es posible que quieras echar un vistazo a http://radikalfx.com/2009/10/16/canvas-collage/. él usa una especie de técnica de "capas". – Matthew

Respuesta

214

No, sin embargo, podría superponer varios elementos <canvas> uno encima del otro y lograr algo similar.

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

Dibuja tu primera capa en el lienzo layer1, y la segunda capa en el lienzo layer2. Luego, cuando clearRect en la capa superior, se mostrará todo lo que está en el lienzo inferior.

+3

Gracias por su respuesta. Un bemol: z-index no zIndex;) – Gregoire

+0

Gracias, actualizado. – jimr

+0

¿hay alguna manera de ocultar/mostrar una capa ... de modo que pueda ocultar la capa 1 y mostrar la capa2 y viceversa cuando sea necesario? – Zaraki

26

En relación con esto:

Si usted tiene algo en el lienzo y quiere dibujar algo en la parte posterior de la misma - se puede hacer cambiando el ajuste context.globalCompositeOperation a 'destino en off' - y luego, devuélvalo a 'source-over' cuando haya terminado.

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

Se pueden crear múltiples elementos canvas sin añadiéndolos en el documento. Estas serán sus capas :

Entonces haz lo que quieras con ellos y al final acaba de hacer que su contenido en el orden correcto en el lienzo de destino mediante drawImage en context.

+0

Asesino de rendimiento. Aproximadamente ~ 10 veces más lento. – SCLeo

+2

@SCLeo dijiste "Rendimiento asesino. Aproximadamente ~ 10 veces más lento" es completamente incorrecto. Dependiendo de los casos de uso, utilizar un lienzo de DOM único y renderizar lienzos fuera de pantalla es más rápido que apilar lienzo en DOM. El error común es comparar las llamadas de representación, las llamadas al sorteo de lienzos se pueden cronometrar, el renderizado de DOM está fuera del contexto de Javascripts y no se puede temporizar. El resultado es que el lienzo de be DOM no recibe el render de composición (hecho por DOM) incluido en el benchmark .. – Blindman67

+0

@ Blindman67 Sé lo que quieres decir. Simplemente presiona este punto de referencia: https://jsfiddle.net/9a9L8k7k/1/. En caso de que malinterprete, hay tres lienzos, lienzo 1 (ctx1) es un lienzo real. Canvas 2 (ctx2) y canvas 3 (ctx) están fuera de pantalla. La imagen ha sido renderizada previamente en ctx3. En la prueba 1 de este benchmark, directamente renderizo ctx3 en ctx1. En la prueba 2, renderizo ctx3 en ctx2 y luego ctx2 en ctx1. La prueba 2 es 30 veces más lenta que la prueba 1 en mi computadora. Es por eso que digo que usar un lienzo intermedio es mucho más lento. – SCLeo

4

Estaba teniendo este mismo problema también, mientras que múltiples elementos de lienzo con posición: absoluto hace el trabajo, si desea guardar el resultado en una imagen, eso no va a funcionar.

Así que seguí adelante e hice un simple "sistema" de capas para codificar como si cada capa tuviera su propio código, pero todo se procesa en el mismo elemento.

https://github.com/federicojacobi/layeredCanvas

tengo la intención de añadir capacidades adicionales, pero por ahora se va a hacer.

Puede hacer varias funciones y llamarlas para "falsificar" capas.

+0

Este es perfecto. – Nadir

2

También puede consultar http://www.concretejs.com que es un marco de lona Html5 moderno y liviano que permite la detección de golpes, capas y muchas otras cosas periféricas. Se pueden hacer cosas como esta:

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

realmente aprecio tu trabajo – Guigui

0

entiendo que la Q no quiere utilizar una biblioteca, pero voy a exponer esto para otros procedentes de las búsquedas de Google. @EricRowell mencionó un buen plugin, pero también hay otro plugin que puedes probar, html2canvas.

En nuestro caso, utilizamos PNG transparentes en capas con z-index como un widget de "generador de productos". Html2canvas funcionó brillantemente para reducir la pila sin forzar imágenes, ni utilizar complejidades, soluciones ni el propio lienzo "sin respuesta". No pudimos hacer esto suavemente/con el lienzo vainilla + JS.

Primero use z-index en divs absolutos para generar contenido estratificado dentro de un contenedor de posición relativa. A continuación, canalice el contenedor a través de html2canvas para obtener un lienzo renderizado, que puede dejar tal como está o salir como una imagen para que un cliente pueda guardarlo.

+0

Si tienes imágenes más pesadas, esto tomará algún tiempo para convertir HTML a lienzo, tuvimos que alejarnos de esto solo porque la renderización tomó mucho tiempo. – Vilius

+0

@Vilius sí una buena llamada en las imágenes pesadas/grandes. Tratamos de mantener imágenes de 300K o menos con no más de 4 capas, de lo contrario, los clientes afectados sentirían el ardor al descargar la imagen final compostada. Curioso, ¿qué pasaste a ese tiempo reducido? – dhaupin

+0

Bueno, cometimos un gran error al usar elementos html para dibujar algo en primer lugar. Debido a que nuestra API devolvió x, y, ancho y alto, pasamos a jscanavs para dibujar la imagen en lugar de usar elementos html. Ten en cuenta que tuvimos algunos problemas con la rotación (los puntos de partida fueron un poco incómodos e impredecibles) y que le aplicamos imágenes con dimensiones específicas, pero finalmente todo se resolvió. También descubrimos que nuestra aplicación de procesamiento de imágenes estaba agotando muchos recursos, por lo que también nos alejamos de eso. – Vilius