CANVAS AVANZADO PARTE I
Guardar y restaurar el estado save() Guarda todo el estado del lienzo. restore() Restaura el estado del lienzo guardado más recientemente. var canvas = document.getElementById("Lienzo"); var ctx = canvas.getContext("2d"); ctx.save(); ctx.fillStyle = 'green'; ctx.fillRect(10, 10, 100, 100); ctx.restore(); ctx.fillRect(150, 75, 100, 100);
Los estados del lienzo se almacenan en una pila. Cada vez que se llama al método save(), el estado del dibujo actual se empuja a la pila. Un estado de dibujo consiste en: 1.Las transformaciones que se han aplicado (es decir, translate, rotate y scale ). 2.Los valores actuales de los siguientes atributos: strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, lineDashOffset, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation, font, textAlign, textBaseline, direction, imageSmoothingEnabled. 3.El trazado de recorte actual Puede llamar al método save() tantas veces como desee. Cada vez que se llama al método restore(), el último estado guardado se elimina de la pila y se restauran todas las configuraciones guardadas.
var canvas = document.getElementById("Lienzo"); var ctx = canvas.getContext("2d"); ctx.fillRect(0, 0, 150, 150); // Dibuja un rectángulo con la configuración predeterminada ctx.save(); ctx.save (); // Guarda el estado predeterminado ctx.fillStyle = '#09F'; // Nuevo cambio a la configuración ctx.fillRect(15, 15, 120, 120); // Dibuja un rectángulo con nueva configuración ctx.save(); // Guarda el estado actual ctx.fillStyle = '#FFF'; // Nuevo cambio a la configuración ctx.globalAlpha = 0.5; ctx.fillRect(30, 30, 90, 90); // Dibuja un rectángulo con nueva configuración ctx.restore(); // Restaura el estado anterior ctx.fillRect(45, 45, 60, 60); // Dibuja un rectángulo con la configuración restaurada ctx.restore(); // Restaurar el estado original ctx.fillRect(60, 60, 30, 30); // Dibuja un rectángulo con la configuración restaurada
Transformaciones Existen formas más potentes de traducir el origen a una posición diferente, girar la cuadrícula e incluso escalarla. translate(x, y) El primero de los métodos de transformación es translate(). Este método se usa para mover el lienzo y su origen a un punto diferente de la cuadrícula. translate(x, y) Mueve el lienzo y su origen en la grilla. x indica la distancia horizontal para moverse, e y indica qué tan lejos mover la rejilla verticalmente. Es una buena idea guardar el estado del lienzo antes de realizar cualquier transformación. En la mayoría de los casos, es más fácil llamar al método de restore que tener que hacer una traducción inversa para volver al estado original. Además, si está traduciendo dentro de un bucle y no guarda y restaura el estado del lienzo, podría terminar perdiendo parte del dibujo, ya que se dibujó fuera del borde del lienzo.
var canvas = document.getElementById("Lienzo"); var ctx = canvas.getContext("2d"); for (var i = 0; i < 3; i++) { for (var j = 0; j < 3; j++) { ctx.save(); ctx.fillStyle = 'rgb(' + (51 * i) + ', ' + ( * i) + ', 255)'; ctx.translate(10 + j * 50, 10 + i * 50); ctx.fillRect(0, 0, 25, 25); ctx.restore(); } } Este ejemplo demuestra algunos de los beneficios de traducir el origen del lienzo. Sin el método translate(), todos los rectángulos se dibujarían en la misma posición (0,0). El método translate() también nos da la libertad de colocar el rectángulo en cualquier parte del lienzo sin tener que ajustar manualmente las coordenadas en la función fillRect(). Esto hace que sea un poco más fácil de entender y usar. En la función draw(), llamamos a la función fillRect() nueve veces utilizando dos bucles for. En cada bucle, el lienzo se traduce, se dibuja el rectángulo y el lienzo vuelve a su estado original. Observe cómo la llamada a fillRect() usa las mismas coordenadas cada vez, confiando en translate() para ajustar la posición del dibujo. Este ejemplo demuestra algunos de los beneficios de traducir el origen del lienzo. Sin el método translate(), todos los rectángulos se dibujarían en la misma posición (0,0). El método translate() también nos da la libertad de colocar el rectángulo en cualquier parte del lienzo sin tener que ajustar manualmente las coordenadas en la función fillRect(). Esto hace que sea un poco más fácil de entender y usar. En la función draw(), llamamos a la función fillRect() nueve veces utilizando dos bucles for. En cada bucle, el lienzo se traduce, se dibuja el rectángulo y el lienzo vuelve a su estado original. Observe cómo la llamada a fillRect() usa las mismas coordenadas cada vez, confiando en translate() para ajustar la posición del dibujo.
Método setTransform () setTransform () le permite escalar, rotar, mover y sesgar el contexto actual. setTransform ( a, b, c, d, e, f ); var canvas = document.getElementById("Lienzo"); var ctx = canvas.getContext("2d"); var i =0.1; function mostrar(){ ctx.clearRect(50,50,250,100); ctx.setTransform(i, 0, 0, 1, 0, 0); ctx.fillStyle = 'lightblue'; ctx.fillRect(50, 50, 250, 100); ctx.fillStyle = 'red'; ctx.font = '30px Arial'; ctx.fillText('Transform', 60, 80); i += 0.4; if (i>4) clearInterval(intervalID); } intervalID=setInterval("mostrar()",500); Parameter Description a Escala Horizontal b Rotación Horizontal c Rotación Vertical d Escala Vertical e Desplazamiento Horizontal f Desplazamiento Vertical Restablece la transformación actual a la matriz de identidad y luego invoca el método transform() con los mismos argumentos. Esto básicamente deshace la transformación actual, luego establece la transformación especificada, todo en un solo paso. resetTransform() Restablece la transformación actual a la matriz de identidad. Esto es lo mismo que llamar: ctx.setTransform(1, 0, 0, 1, 0, 0);
var canvas = document.getElementById("Lienzo"); var ctx = canvas.getContext("2d"); var i =-2; function mostrar(){ ctx.clearRect(50,50,250,100); ctx.setTransform(1, i, 0, 1, 0, 0); ctx.fillStyle = 'lightblue'; ctx.fillRect(50, 50, 250, 100); ctx.fillStyle = 'red'; ctx.font = '30px Arial'; ctx.fillText('Transform', 60, 80); i += 0.5; if (i>2) clearInterval(intervalID); } intervalID=setInterval("mostrar()",500);
var canvas = document.getElementById("Lienzo"); var ctx = canvas.getContext("2d"); var i =-2; function mostrar(){ ctx.clearRect(50,50,250,100); ctx.setTransform(1, 0, i, 1, 0, 0); ctx.fillStyle = 'lightblue'; ctx.fillRect(50, 50, 250, 100); ctx.fillStyle = 'red'; ctx.font = '30px Arial'; ctx.fillText('Transform', 60, 80); i += 0.5; if (i>2) clearInterval(intervalID); } intervalID=setInterval("mostrar()",500);
var canvas = document.getElementById("Lienzo"); var ctx = canvas.getContext("2d"); var i =0.1; function mostrar(){ ctx.clearRect(50,50,250,100); ctx.setTransform(1, 0, 1, i, 0, 0); ctx.fillStyle = 'lightblue'; ctx.fillRect(50, 50, 250, 100); ctx.fillStyle = 'red'; ctx.font = '30px Arial'; ctx.fillText('Transform', 60, 80); i += 0.4; if (i>3) clearInterval(intervalID); } intervalID=setInterval("mostrar()",500);
var canvas = document.getElementById("Lienzo"); var ctx = canvas.getContext("2d"); var i =-200; function mostrar(){ ctx.clearRect(50,50,250,100); ctx.setTransform(1, 0, 0, 1, i, 0); ctx.fillStyle = 'lightblue'; ctx.fillRect(50, 50, 250, 100); ctx.fillStyle = 'red'; ctx.font = '30px Arial'; ctx.fillText('Transform', 60, 80); i += 50; if (i>200) clearInterval(intervalID); } intervalID=setInterval("mostrar()",500);
var canvas = document.getElementById("Lienzo"); var ctx = canvas.getContext("2d"); var i =0; function mostrar(){ ctx.clearRect(50,50,250,100); ctx.setTransform(1, 0, 0, 1, 0, i); ctx.fillStyle = 'lightblue'; ctx.fillRect(50, 50, 250, 100); ctx.fillStyle = 'red'; ctx.font = '30px Arial'; ctx.fillText('Transform', 60, 80); i += 30; if (i>200) clearInterval(intervalID); } intervalID=setInterval("mostrar()",500);
Dibuja un rectángulo, restablece y crea una nueva matriz de transformación con setTransform (), dibuja el rectángulo de nuevo, restablece y crea una nueva matriz de transformación, luego dibuja el rectángulo nuevamente. Observar que cada vez que llama a setTransform (), restablece la matriz de transformación anterior y luego crea la nueva matriz, por lo que en el ejemplo siguiente, el rectángulo rojo no se muestra, porque está debajo del rectángulo azul Ejemplo var canvas = document.getElementById("Lienzo"); var ctx = canvas.getContext("2d"); ctx.fillStyle="yellow"; ctx.fillRect(0,0,250,100); ctx.setTransform(1,0.5,-0.5,1,30,10); ctx.fillStyle="red"; ctx.fillRect(0,0,250,100); ctx.setTransform(1,0.5,-0.5,1,30,10); ctx.fillStyle="blue"; ctx.fillRect(0,0,250,100);
var canvas = document.getElementById("Lienzo"); var ctx = canvas.getContext("2d"); ctx.fillStyle="yellow"; ctx.fillRect(0,0,250,100); ctx.setTransform(1,0.5,-0.5,1,30,10); ctx.fillStyle="red"; ctx.fillRect(0,0,250,100); ctx.setTransform(1,1,-0.5,1,30,10); ctx.fillStyle="blue"; ctx.fillRect(0,0,250,100);
var canvas = document.getElementById("Lienzo"); var ctx = canvas.getContext("2d"); ctx.fillStyle="yellow"; ctx.fillRect(0,0,250,100); ctx.setTransform(1,0.5,-0.5,1,30,10); ctx.fillStyle="red"; ctx.fillRect(0,0,250,100); ctx.setTransform(1,0.5,1,1,30,10); ctx.fillStyle="blue"; ctx.fillRect(0,0,250,100);
var ctx = document.getElementById('Lienzo').getContext('2d'); var sin = Math.sin(Math.PI / 6); var cos = Math.cos(Math.PI / 6); ctx.translate(100, 100); var c = 0; for (var i = 0; i <= 12; i++) { c = Math.floor(255 / 12 * i); ctx.fillStyle = 'rgb(' + c + ', ' + c + ', ' + c + ')'; ctx.fillRect(0, 0, 100, 10); ctx.transform(cos, sin, -sin, cos, 0, 0); } ctx.setTransform(-1, 0, 0, 1, 100, 100); ctx.fillStyle = 'rgba(255, 128, 255, 0.5)'; ctx.fillRect(0, 50, 100, 100);
PROPIEDAD GLOBALCOMPOSITEOPERATION La propiedad globalCompositeOperation establece o devuelve cómo una imagen fuente (nueva) se dibuja en una imagen de destino (existente). imagen de origen = dibujos que está a punto de colocar en el lienzo. imagen de destino = dibujos que ya están colocados en el lienzo. contexto.globalCompositeOperation = "constante";
Ejemplo Dibujar rectángulos utilizando dos valores diferentes globalCompositeOperation. Los rectángulos rojos son imágenes de destino. Los rectángulos azules son imágenes de origen : var ctx = document.getElementById('Lienzo').getContext('2d'); ctx.fillStyle="red"; ctx.fillRect(20,20,75,50); ctx.globalCompositeOperation="source-over"; ctx.fillStyle="blue"; ctx.fillRect(50,50,75,50); ctx.fillStyle="red"; ctx.fillRect(150,20,75,50); ctx.globalCompositeOperation="destination-over"; ctx.fillStyle="blue"; ctx.fillRect(180,50,75,50);
Trazados de recorte (máscara de recorte) Un trazado de recorte es como una forma de lienzo normal, pero actúa como una máscara para ocultar partes de formas no deseadas. Esto se visualiza en la imagen de la derecha. La forma de estrella roja es nuestro camino de recorte. Todo lo que queda fuera de este camino no se dibujará en el lienzo. Si comparamos los trazados de recorte con la propiedad globalCompositeOperation que hemos visto anteriormente, vemos dos modos de composición que logran más o menos el mismo efecto en source-in y source- atop. Las diferencias más importantes entre los dos son que los trazados de recorte nunca se dibujan realmente en el lienzo y el trazado de recorte nunca se ve afectado por la adición de nuevas formas. Esto hace que los trazados de recorte sean ideales para dibujar formas múltiples en un área restringida.