domingo, 24 de enero de 2016

Dibujar gráficos en HTML - 3 de 3



  • Sombras
Por supuesto, sombras son también una parte importante de Canvas API. Podemos generar sombras para cada trazado e incluso textos. La API provee cuatro propiedades para hacerlo:
  • shadowColor :Esta propiedad declara el color de la sombra usando sintaxis CSS.
  • shadowOffsetX :Esta propiedad recibe un número para determinar qué tan lejos la sombra estará ubicada del objeto (dirección horizontal).
  • shadowOffsetY :Esta propiedad recibe un número para determinar qué tan lejos la sombra estará ubicada del objeto (dirección vertical).
  • shadowBlur :Esta propiedad produce un efecto de difuminación para la sombra.


Código 7-17. Aplicando sombras.

function iniciar(){
var elemento=document.getElementById('lienzo');
lienzo=elemento.getContext('2d');
lienzo.shadowColor="rgba(0,0,0,0.5)";
lienzo.shadowOffsetX=4;
lienzo.shadowOffsetY=4;
lienzo.shadowBlur=5;
lienzo.font="bold 50px verdana, sans-serif";
lienzo.fillText("Mi mensaje ", 100,100);
}
window.addEventListener("load", iniciar, false);

La sombra creada en el Código 7-17 usa la función rgba() para obtener un color negro semitransparente. Es desplazada 4 pixeles del objeto y tiene un valor de difuminación de 5.
Hágalo usted mismo: Aplique sombras a otra figura en lugar de texto. Por ejemplo, pruebe generar sombras para figuras vacías y sólidas, usando rectángulos o círculos.

  • Transformaciones

LA API Canvas ofrece operaciones complejas que es posible aplicar sobre el lienzo para afectar los gráficos que luego son dibujados en él. Estas operaciones son realizadas utilizando cinco métodos de transformación diferentes, cada uno para un propósito específico. 
  • translate(x, y) :Este método de transformación es usado para mover el origen del lienzo. Cada lienzo comienza en el punto 0,0 localizado en la esquina superior izquierda, y los valores se incrementan en cualquier dirección dentro del lienzo. Valores negativos caen fuera del lienzo. A veces es bueno poder usar valores negativos para crear figuras complejas. El método translate() nos permite mover el punto 0,0 a una posición específica para usar el origen como referencia para nuestros dibujos o para aplicar otras transformaciones.
  • rotate(ángulo) :Este método de transformación rotará el lienzo alrededor del origen tantos ángulos como sean especificados.
  • scale(x, y) :Este método de transformación incrementa o disminuye las unidades de la grilla para reducir o ampliar todo lo que esté dibujado en el lienzo. La escala puede ser cambiada independientemente para el valor horizontal o vertical usando los atributos x e y. Los valores pueden ser negativos, produciendo un efecto de espejo. Por defecto los valores son iguales a 1.0.
  • transform(m1, m2, m3, m4, dx, dy) :El lienzo contiene una matriz de valores que especifican sus propiedades. El método transform() aplica una nueva matriz sobre la actual para modificar el lienzo.
  • setTransform(m1, m2, m3, m4, dx, dy) :Este método reinicializa la actual matriz de transformación y establece una nueva desde los valores provistos en sus atributos.


Código 7-18. Moviendo, rotando y escalando.

function iniciar(){
var elemento=document.getElementById('lienzo');
lienzo=elemento.getContext('2d');
lienzo.font="bold 20px verdana, sans-serif";
lienzo.fillText("PRUEBA",50,20);
lienzo.translate(50,70);
lienzo.rotate(Math.PI/180*45);
lienzo.fillText("PRUEBA",0,0);
lienzo.rotate(-Math.PI/180*45);
lienzo.translate(0,100);
lienzo.scale(2,2);
lienzo.fillText("PRUEBA",0,0);
}
window.addEventListener("load", iniciar, false);

No hay mejor forma de entender cómo funcionan las transformaciones que usarlas en nuestro código. En el Código 7-18, aplicamos los métodos translate(), rotate() y scale() al mismo texto. Primero dibujamos un texto en el lienzo con la configuración por defecto. El texto aparecerá en la posición 50,20 con un tamaño de 20 pixeles. Luego de esto, usando translate(), el origen del lienzo es movido a la posición 50,70 y el lienzo completo es rotado 45 grados con el método rotate(). Otro texto es dibujado en el nuevo origen, con una inclinación de 45 grados. Las transformaciones aplicadas se vuelven los valores por defecto, por lo tanto antes de aplicar el siguiente método scale() rotamos el lienzo 45 grados negativos para ubicarlo en su posición original. Realizamos una transformación más moviendo el origen otros 100 pixeles hacia abajo. Finalmente, la escala del lienzo es duplicada y un nuevo texto es dibujado al doble del tamaño de los anteriores.
Cada transformación es acumulativa. Si realizamos dos transformaciones usando scale(), por ejemplo, el segundo método realizará el escalado considerando el estado actual del lienzo. Una orden scale(2,2) luego de otra scale(2,2) cuadruplicará la escala del lienzo. Y para los métodos de transformación de la matriz, esta no es una excepción. Es por esto que contamos con dos métodos para realizar esta clase de transformaciones: transform() y setTransform().

Código 7-19. Transformaciones acumulativas sobre la matriz.

function iniciar(){
var elemento=document.getElementById('lienzo');
lienzo=elemento.getContext('2d');
lienzo.transform(3,0,0,1,0,0);
lienzo.font="bold 20px verdana, sans-serif";
lienzo.fillText("PRUEBA",20,20);
lienzo.transform(1,0,0,10,0,0);
lienzo.font="bold 20px verdana, sans-serif";
lienzo.fillText("PRUEBA",100,20);
}
window.addEventListener("load", iniciar, false);

Al igual que en el código anterior, en el Código 7-19 aplicamos varios métodos de transformación sobre el mismo texto para comparar efectos. Los valores por defecto de la matriz del lienzo son 1,0,0,1,0,0. Cambiando el primer valor a 3, en la primera transformación de nuestro ejemplo arriba, estiramos el lienzo horizontalmente. El texto dibujado luego de esta transformación será más ancho que en condiciones por defecto.
Con la siguiente transformación, el lienzo fue estirado verticalmente cambiando el cuarto valor a 10 y preservando los anteriores.
Un detalle importante a recordar es que las transformaciones son aplicadas sobre la matriz declarada en previas transformaciones, por lo que el segundo texto mostrado por el código del Código 7-19 será igual de ancho que el anterior (es estirado horizontal y verticalmente). Para reinicializar la matriz y declarar nuevos valores de transformación, podemos usar el método setTransform()
Hágalo usted mismo: Reemplace el último método transform() en el ejemplo por setTransform() y compruebe los resultados. Usando solo un texto, cambie cada valor en el método transform() para conocer la clase de transformación realizada en el lienzo por cada uno de ellos.

  • Restaurando el estado

La acumulación de transformaciones hace realmente difícil volver a anteriores estados. En el código del Código 7-18, por ejemplo, tuvimos que recordar el valor de rotación usado previamente para poder realizar una nueva rotación y volver el lienzo al estado original. 
Considerando situaciones como ésta, Canvas API provee dos métodos para grabar y recuperar el estado del lienzo. 
  • save() :Este método graba el estado del lienzo, incluyendo transformaciones ya aplicadas, valores de propiedades de estilo y la actual máscara (el área creada por el método clip(), si existe).
  • restore() :Este método recupera el último estado grabado.


Código 7-20. Grabando el estado del lienzo.

function iniciar(){
var elemento=document.getElementById('lienzo');
lienzo=elemento.getContext('2d');
lienzo.save();
lienzo.translate(50,70);
lienzo.font="bold 20px verdana, sans-serif";
lienzo.fillText("PRUEBA1",0,30);
lienzo.restore();
lienzo.fillText("PRUEBA2",0,30);
}
window.addEventListener("load", iniciar, false);

Si ejecuta el código del Código 7-20 en su navegador, verá el texto “PRUEBA1” en grandes letras al centro del lienzo, y el texto “PRUEBA2” en letras pequeñas, cercano al origen. Lo que hicimos fue grabar el estado por defecto del lienzo y luego establecer una nueva posición para el origen y estilos para el texto. El primer texto es dibujado con esta configuración, pero antes de dibujar el segundo texto el estado original es restaurado, por lo que este texto es mostrado con los estilos por defecto, no con los declarados para el primero.
No importa cuántas transformaciones hayamos realizado, luego de llamar al método restore() la configuración del lienzo será retornada exactamente a su estado anterior (el último grabado).

  • globalCompositeOperation

Cuando hablamos de trazados dijimos que existe una propiedad para determinar cómo una figura es posicionada y combinada con figuras dibujadas previamente en el lienzo. La propiedad es globalCompositeOperation y su valor por defecto es source-over, lo que significa que la nueva figura será dibujada sobre las que ya existen en el lienzo. La propiedad ofrece 11 valores más:
  • source-in :Solo la parte de la nueva figura que se sobrepone a las figuras previas es dibujada. El resto de la figura, e incluso el resto de las figuras previas, se vuelven transparentes.
  • source-out :Solo la parte de la nueva figura que no se sobrepone a las figuras previas es dibujada. El resto de la figura, e incluso el resto de las figuras previas, se vuelven transparentes.
  • source-atop :Solo la parte de la nueva figura que se superpone con las figuras previas es dibujada. Las figuras previas son preservadas, pero el resto de la nueva figura se vuelve transparente.
  • lighter :Ambas figuras son dibujadas (nueva y vieja), pero el color de las partes que se superponen es obtenido adicionando los valores de los colores de cada figura.
  • xor :Ambas figuras son dibujadas (nueva y vieja), pero las partes que se superponen se vuelven transparentes.
  • destination-over :Este es el opuesto del valor por defecto. Las nuevas figuras son dibujadas detrás de las viejas que ya se encuentran en el lienzo.
  • destination-in :Las partes de las figuras existentes en el lienzo que se superponen con la nueva figura son preservadas. El resto, incluyendo la nueva figura, se vuelven transparentes.
  • destination-out :Las partes de las figuras existentes en el lienzo que no se superponen con la nueva figura son preservadas. El resto, incluyendo la nueva figura, se vuelven transparentes.
  • destination-atop :Las figuras existentes y la nueva son preservadas solo en la parte en la que se superponen.

  • darker :Ambas figuras son dibujadas, pero el color de las partes que se superponen es determinado substrayendo los valores de los colores de cada figura.
  • copy :Solo la nueva figura es dibujada. Las ya existentes se vuelven transparentes.


Código 7-21. Probando la propiedad globalCompositeOperation.

function iniciar(){
var elemento=document.getElementById('lienzo');
lienzo=elemento.getContext('2d');
lienzo.fillStyle="#990000";
lienzo.fillRect(100,100,300,100);
lienzo.globalCompositeOperation="destination-atop";
lienzo.fillStyle="#AAAAFF";
lienzo.font="bold 80px verdana, sans-serif";
lienzo.textAlign="center";
lienzo.textBaseline="middle";
lienzo.fillText("PRUEBA",250,110);
}
window.addEventListener("load", iniciar, false);

Solo representaciones visuales de cada posible valor para la propiedad globalCompositeOperation le ayudarán a comprender cómo funcionan. Con este propósito, preparamos el código del Código 7-21. Cuando este código es ejecutado, un rectángulo rojo es dibujado en el medio del lienzo, pero gracias al valor destination-atop solo la parte del rectángulo que se superpone con el texto es dibujada.
Hágalo usted mismo: Reemplace el valor destination-atop con cualquiera de los demás valores posibles para esta propiedad y compruebe el resultado en su navegador. Pruebe el código en distintos navegadores.

Espero haber ayudado en algo. Hasta la próxima oportunidad!










  

No hay comentarios:

Publicar un comentario en la entrada