Dibujando gráficos con canvas

by 2 contributors:

Most of this content (but not the documentation on drawWindow) has been rolled into the more expansive Canvas tutorial, this page should probably be redirected there as it's now redundant but some information may still be relevant.

Introduction

Firefox 1.5, incluye un nuevo elemento HTML para gráficos programables.   <canvas> está basado en la especificación de canvas WHATWG, la que a su vez está basada en el <canvas> de Apple, implementado en Safari.   Puede ser usado para la renderización de gráficos, elementos de Interfaz de usuarios, y otros gráficos personalizados en el cliente.

La etiqueta <canvas> crea una superficie de dibujo de tamaño fijo que expone uno o más contextos de renderizado.   Nos enfocaremos en la representación del contexto 2D   Para gráficos 3D, podrías usar la representación del contexto WebGL

El contexto de representación 2D

Un ejemplo sencillo

Para comenzar, aquí un sencillo ejemplo que dibuja dos rectángulos interesándose, uno de los cuales tiene transparencia alfa.

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');

  ctx.fillStyle = "rgb(200,0,0)";
  ctx.fillRect (10, 10, 55, 50);

  ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
  ctx.fillRect (30, 30, 55, 50);
}

ScreenshotLive sample

La funcion draw obtiene el elemento canvas, entonces obtiene el contexto 2D.   El objeto ctx puede entonces actualmente ser renderizado para el canvas   El ejemplo simplemente llena dos rectangulos, configurando fillStyle a dos diferentes colores utilizando las especificaciones de color de CSS y llamando a fillRect   El segundo FillStyle usa rgba() para especificar un valor alpha junto con el color.

El fillRect, strokeRect, y clearRect llama a render a ser llenado, bosquejado o limpiar rectangulo.   Para representar formas más complejas, se usan trayectorias.  

Usando trayectorias

La funcion Path inicia un nuevo trazo, y move to, line to, arc to, arc, y metodos similares son usados para agregar segmentos al trazo.   La trayectoria puede ser cerrada usando closePath   Una vez la trayectoria es creada, puedes usar fill o stroke para representar la trayectoria en el canvas.

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');

  ctx.fillStyle = "red";

  ctx.beginPath();
  ctx.moveTo(30, 30);
  ctx.lineTo(150, 150);
  // was: ctx.quadraticCurveTo(60, 70, 70, 150); which is wrong.
  ctx.bezierCurveTo(60, 70, 60, 70, 70, 150); // <- this is right formula for the image on the right ->
  ctx.lineTo(30, 30);
  ctx.fill();
}

ScreenshotLive sample

Llamando fill() o stroke() causa que el trazo sea usado.   Para ser llenado o juntado otra vez, el trazo debe ser recreado.

Estado de gráficos

Los atributos del contexto como fillStyle, strokeStyle, lineWidth, y lineJoin son parte de actual estado de graficos   El contexto provee dos metodos, save() y restore(), que pueden ser usados para mover el actual estado y desde estado stack.

Un ejemplo más complicado

Hay aquì un ejemplo más complicado, que usa rutas,estado y tambien introduce la actual matriz de transformación.   Los metodos de contexto translate(), scale(), y rotate() todos transforman la matriz actual.   Todos los puntos renderizados son primero transformados por esta matriz.

function drawBowtie(ctx, fillStyle) {
 
  ctx.fillStyle = "rgba(200,200,200,0.3)";
  ctx.fillRect(-30, -30, 60, 60);
 
  ctx.fillStyle = fillStyle;
  ctx.globalAlpha = 1.0;
  ctx.beginPath();
  ctx.moveTo(25, 25);
  ctx.lineTo(-25, -25);
  ctx.lineTo(25, -25);
  ctx.lineTo(-25, 25);
  ctx.closePath();
  ctx.fill();
}
 
function dot(ctx) {
  ctx.save();
  ctx.fillStyle = "yellow";
  ctx.fillRect(-2, -2, 4, 4);
  ctx.restore();
}
 
function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');

  // note that all other translates are relative to this one
  ctx.translate(45, 45);

  ctx.save();
  //ctx.translate(0, 0); // unnecessary
  drawBowtie(ctx, "red");
  dot(ctx);
  ctx.restore();
 
  ctx.save();
  ctx.translate(85, 0);
  ctx.rotate(45 * Math.PI / 180);
  drawBowtie(ctx, "green");
  dot(ctx);
  ctx.restore();
 
  ctx.save();
  ctx.translate(0, 85);
  ctx.rotate(135 * Math.PI / 180);
  drawBowtie(ctx, "blue");
  dot(ctx);
  ctx.restore();
 
  ctx.save();
  ctx.translate(85, 85);
  ctx.rotate(90 * Math.PI / 180);
  drawBowtie(ctx, "yellow");
  dot(ctx);
  ctx.restore();
}

ScreenshotLive sample

Esto define dos métodos, lazo y punto, que son llamados 4 veces.   Antes de cada llamada, los metodos translate() y rotate() son utilizados para la matriz de transformación actual, que a su vez posicionara el punto y el lazo.   el punto presenta un pequeño cuadrado negro centrado a (0,0).   Ese punto se mueve alrededor de la matriz de transformación.   El lazo presenta un simple ruta de lazo usando el estillo de llenado pasado.

Como las operaciones de la matriz son acumulativas, save() y restore() son utilizados para cada conjunto de llamadas para restaurar el estado de canvas original.   Una cosa a tener en cuenta es que la rotación siempre se produce en torno al origen actual, por lo que a traducir () rotate () translate () secuencia producirá resultados diferentes a traducir () translate () serie de llamadas rotate ().

Compatibilidad con Apple <canvas>

En su mayor parte, <canvas> es compatible con Apple y otras implementaciones.   Hay, sin embargo, algunas cuestiones a tener en cuenta, que se describen aquí.

Etiqueta </canvas> requerida 

En la aplicación de Apple Safari, <canvas> es un elemento ejecutado de la misma manera <img> es, sino que no tiene una etiqueta de cierre.   Sin embargo, para <canvas> tener uso generalizado en la web, se debe proporcionar alguna facilidad para contenido de reserva.   Por lo tanto, la implementación de Mozilla tiene una etiqueta de cierre requerida.

Si no se necesita contenido de reserva, un simple <canvas id="foo" ...> </ canvas> será totalmente compatible con Safari y Mozilla - Safari simplemente ignorar la etiqueta de cierre.

Si se desea contenido de reserva, algunos trucos CSS se deben emplear para enmascarar el contenido de reserva desde Safari (las cuales deben emitir sólo la tela), y también para enmascarar los propios trucos CSS de IE (que debería hacer que el contenido de reserva).

canvas {
  font-size: 0.00001px !ie;
}

Caracteristicas adicionales  

Renderizando el contenido we dentro de un Canvas.

Esta caracteristica esta solo disponible para codigo ejecutado con privilegios de Chrome.   No esta permitido en paginas HTML normales. Porqué leer.

El canvas de Mozilla se extendio con el metodo drawWindow().   Este metodo dibuja una instantanea de los contenidos de una ventana DOM dentro del canvas. Por ejemplo:

ctx.drawWindow(window, 0, 0, 100, 200, "rgb(255,255,255)");

atraería el contenido de la ventana actual, en el rectángulo (0,0,100,200) en píxeles con respecto a la parte superior izquierda de la ventana, sobre un fondo blanco, en el lienzo.   Mediante la especificación de "rgba (255,255,255,0)" como el color, el contenido no se dibujan con un fondo transparente (lo que sería más lenta).

Normalmente es una mala idea usar un fondo distinto de blanco "rgb(255, 255, 255)" o transparente, esto es lo que hacen todos los navegadores, y muchos sitios web esperan que esas partes transparentes de su interfaz serán puestas en fondo blanco.

Con este metodo, es posible ocupar un IFRAME oculto con contenido arbitrario (por ejemplo, texto HTML con estilo CSS, o SVG) y dibujarlo dentro de un canvas.   sera escalado, rotado y sucesivamente de acuerdo a la transformación actual.

Extensión de previsualización pestaña de Ted Mielczarek utiliza esta técnica en cromo para proporcionar imágenes en miniatura de las páginas web, y la fuente está disponible para su referencia.  

Nota: usar canvas.drawWindow() mientras manejamos un evento de carga de documento, no trabaja   En Firefox 3.5 o superior, puedes hacer esto en un manejador para el evento MozAfterPaint para dibujr satisfactoriamente un contenido HTML dentro de un canvas al cargar la pagina  

See also

Etiquetas y colaboradores del documento

Contributors to this page: teoli, rubencidlara
Última actualización por: teoli,