Aplicación de estilos y colores

 

En el capítulo dedicado a dibujar formas usé sólo los estilos de línea y relleno predeterminados. En este capítulo vamos a explorar todas las opciones de canvas que tenemos a nuestra disposición para hacer que nuestros dibujos sean un poco más atractivos.

Colores

Hasta ahora sólo hemos visto métodos del contexto de dibujo. Si queremos aplicar colores a una forma, hay dos características importantes que podemos utilizar: fillStyle y strokeStyle .

fillStyle = color
strokeStyle = color

strokeStyle se utiliza para configurar el color del contorno de la forma y fillStyle es para el color de relleno. color puede ser una cadena que representa un valor de color CSS, un objeto degradado o un objeto modelo. Prestaremos atención a los objetos degradados y modelos más tarde. De forma predeterminada, el trazo y el color de relleno se establecen en negro (valor de color CSS #000000).

Las cadenas válidas que puedes introducir deben ser, de acuerdo con la especificación, los valores de color CSS3 . Cada uno de los ejemplos siguientes describen el mismo color.

// todos ellos configuran fillStyle a 'naranja' (orange)
ctx.fillStyle = "orange";
ctx.fillStyle = "#FFA500";
ctx.fillStyle = "rgb(255,165,0)";
ctx.fillStyle = "rgba(255,165,0,1)";

Nota: En la actualidad no todos los valores de color CSS 3 son compatibles con el motor Gecko. Por ejemplo, los valores de color hsl(100%,25%,0) o rgb(0,100%,0) no están permitidos. Si te atienes estrictamente a los valores de arriba, no te surgirá ningún problema.

Nota: Si estableces la propiedad strokeStyle o fillStyle, el nuevo valor se convierte en el valor predeterminado para todas las formas que se dibujen a partir de entonces. Para cada forma que desees en un color diferente, tendrás que volver a asignar la propiedad fillStyle o strokeStyle.

Un ejemplo de fillStyle

En este ejemplo, una vez más, utilizo dos bucles for para dibujar una cuadrícula de rectángulos, cada uno en un color diferente. La imagen resultante debe parecerse a la imagen de la derecha. No hay nada excesivamente espectacular en este caso. Uso las dos variables i y j para generar un único color RGB para cada cuadrado. Sólo modifico los valores de rojo y verde. El canal azul tiene un valor fijo. Mediante la modificación de los canales, puedes generar todo tipo de paletas. Al aumentar los pasos, puedes lograr algo que se parece a las paletas de color que utiliza Photoshop.

Ver este ejemplo

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');
  for (var i=0;i<6;i++){
    for (var j=0;j<6;j++){
      ctx.fillStyle = 'rgb(' + Math.floor(255-42.5*i) + ',' + 
                       Math.floor(255-42.5*j) + ',0)';
      ctx.fillRect(j*25,i*25,25,25);
    }
  }
}

 

Un ejemplo de strokeStyle

Este ejemplo es similar al anterior pero ahora con la propiedad strokeStyle. Aquí utilizo el método arc para dibujar círculos en lugar de cuadrados.

Ver este ejemplo

   function draw() {
    var ctx = document.getElementById('canvas').getContext('2d');
    for (var i=0;i<6;i++){
      for (var j=0;j<6;j++){
        ctx.strokeStyle = 'rgb(0,' + Math.floor(255-42.5*i) + ',' + 
                         Math.floor(255-42.5*j) + ')';
        ctx.beginPath();
        ctx.arc(12.5+j*25,12.5+i*25,10,0,Math.PI*2,true);
        ctx.stroke();
      }
    }
  }

Transparencias

Además de dibujar formas opacas en el lienzo, también podemos dibujar formas semitransparentes. Esto se hace mediante el establecimiento de la propiedad globalAlpha o podríamos asignar un color semitransparente al trazo y/o al estilo de relleno.

globalAlpha = transparency value

Esta propiedad aplica un valor de transparencia a todas las formas dibujadas en el lienzo. El rango válido de valores es de 0.0 (totalmente transparente) a 1.0 (totalmente opaco). De forma predeterminada, esta propiedad se establece en 1.0 (totalmente opaco).

La propiedad globalAlpha puede ser útil si deseas dibujar un montón de formas en el lienzo con una transparencia similar. Creo, sin embargo, que la siguiente opción es un poco más práctica.

Debido a que las propiedades strokeStyle y fillStyle aceptan valores de color CSS 3, podemos utilizar la siguiente notación para asignarles un color transparente.

/ / Asignación de colores transparentes para trazo y estilo de relleno
ctx.strokeStyle = "rgba (255,0,0,0.5)";
ctx.fillStyle = "rgba (255,0,0,0.5)";

La función rgba() es similar a la función rgb(), pero tiene un parámetro adicional. El último parámetro establece el valor de transparencia de este color en particular. El rango válido es de nuevo entre 0.0 (totalmente transparente) y 1.0 (totalmente opaco).

Un ejemplo de globalAlpha

En este ejemplo he dibujado un fondo de cuatro cuadrados de colores diferentes. En la parte superior de estos, he dibujado un conjunto de círculos semitransparentes. La propiedad globalAlpha se establece en 0.2, que se utilizará para todas las formas a partir de ese momento. Cada paso en el bucle for dibuja una serie de círculos con un radio cada vez mayor. El resultado final es un degradado radial. Mediante la superposición de más círculos unos encima de otros, reducimos eficazmente la transparencia de los círculos que ya se han dibujado. Al aumentar el número de pasos y, de hecho, dibujar más círculos, el fondo desaparecería completamente del centro de la imagen.

Ten en cuenta:
  • Este ejemplo no funciona en Firefox 1.5 beta 1. Tendrás que crear una binario diario de una rama estable (como
    mozilla1.9.2) o esperar a una nueva versión para ver esto en acción.
  • Este ejemplo se rompe en Safari ya que el color no se especifica correctamente. El color del ejemplo se especifica como '#09F) ', que no es válido de acuerdo con las especificaciones. Firefox, sin embargo, acepta la definición de color con formato incorrecto.

Ver este ejemplo

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');
  // dibujar fondo
  ctx.fillStyle = '#FD0';
  ctx.fillRect(0,0,75,75);
  ctx.fillStyle = '#6C0';
  ctx.fillRect(75,0,75,75);
  ctx.fillStyle = '#09F';
  ctx.fillRect(0,75,75,75);
  ctx.fillStyle = '#F30';
  ctx.fillRect(75,75,150,150);
  ctx.fillStyle = '#FFF';

  // establecer valor de transparencia
  ctx.globalAlpha = 0.2;

  // Dibujar círculos semitransparentes
  for (var i=0;i<7;i++){
      ctx.beginPath();
      ctx.arc(75,75,10+10*i,0,Math.PI*2,true);
      ctx.fill();
  }
}

Un ejemplo usando rgba()

 En este segundo ejemplo he hecho algo similar a lo anterior, pero en vez de dibujar círculos unos encima de otros, he dibujado pequeños rectángulos con una opacidad creciente. El uso de rgba() te da un poco de más control y flexibilidad, ya que puedes establecer el estilo de relleno y de trazo de manera individual.

Ver este ejemplo

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

  // Dibujar fondo
  ctx.fillStyle = 'rgb(255,221,0)';
  ctx.fillRect(0,0,150,37.5);
  ctx.fillStyle = 'rgb(102,204,0)';
  ctx.fillRect(0,37.5,150,37.5);
  ctx.fillStyle = 'rgb(0,153,255)';
  ctx.fillRect(0,75,150,37.5);
  ctx.fillStyle = 'rgb(255,51,0)';
  ctx.fillRect(0,112.5,150,37.5);

  // Dibujar rectángulos semitransparentes
  for (var i=0;i<10;i++){
    ctx.fillStyle = 'rgba(255,255,255,'+(i+1)/10+')';
    for (var j=0;j<4;j++){
      ctx.fillRect(5+i*14,5+j*37.5,14,27.5)
    }
  }
}

Estilos de línea

Hay varias propiedades que nos permiten aplicar estilo a las líneas.

lineWidth = value
lineCap = type
lineJoin = type
miterLimit = value

Podría describirlas en detalle, pero probablemente se resultará más claro con sólo mirar los ejemplos a continuación.

Un ejemplo de lineWidth

Esta propiedad establece el grosor de la línea actual. Los valores deben ser números positivos. Por defecto, este valor se establece en 1.0 unidades.

El ancho de línea es el espesor del trazo centrado en la ruta dada. En otras palabras, el área que se dibuja se extiende hasta la mitad del ancho de la línea a cada lado de la ruta. Debido a que las coordenadas del lienzo no hacen referencia directamente a los píxeles, se debe prestar especial atención para obtener líneas horizontales y verticales nítidas.

En el siguiente ejemplo, se dibujan 10 líneas rectas con anchos de línea cada vez mayores. La línea en el extremo izquierdo es de 1.0 unidades de ancho. Sin embargo, la línea más a la izquierda y todas las demás cuyo grosor tiene un ancho impar no tienen un borde nítido debido al posicionamiento de la ruta.

Ver este ejemplo

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');
  for (var i = 0; i < 10; i++){
    ctx.lineWidth = 1+i;
    ctx.beginPath();
    ctx.moveTo(5+i*14,5);
    ctx.lineTo(5+i*14,140);
    ctx.stroke();
  }
}

Para obtener líneas nítidas se necesita comprender cómo se trazan las rutas. En las imágenes de abajo, la cuadrícula representa la cuadrícula de las coordinadas del lienzo. Los cuadrados entre las líneas de división son en píxeles reales en pantalla. En la primera imagen de la cuadrícula de abajo, está relleno un rectángulo desde (2,1) hasta (5,5). Toda la zona entre ellos (rojo claro) se encuentre dentro de los límites del píxel, por lo que el rectángulo relleno resultante tendrá bordes nítidos.

Si consideras una ruta desde (3,1) hasta (3,5) con un grosor de línea de 1.0, obtendrás el resultado que se muestra en la segunda imagen. El área real que se va a rellenar (azul oscuro), sólo se extiende hasta la mitad de los píxeles situados a cada lado de la ruta. Se tiene que representar una aproximación de esto, lo que significa que dichos píxeles se sombrean sólo parcialmente, dando como resultado que toda la zona (azul claro y azul oscuro) se rellene con un color sólo la mitad de oscuro que el color del trazo actual. Esto es lo que sucede con la línea de ancho de 1.0 en el código del ejemplo anterior.

Para solucionar este problema, tienes que ser muy preciso a la hora de crear la ruta. Sabiendo que una línea de ancho 1.0 se extenderá la mitad de una unidad a cada lado de la ruta, la creación de la ruta desde (3.5,1) hasta (3.5,5) da como resultado lo que vemos en la tercera imagen: el ancho de línea 1.0 termina rellenando por completo y con precisión una sola línea vertical de píxeles.

Para las líneas de ancho par, cada mitad termina siendo una cantidad entera de píxeles, por lo que es mejor una ruta que esté entre los píxeles (es decir, (3,1) a (3,5)), en lugar de por debajo de la mitad de los píxeles. Además, ten en cuenta que en nuestro ejemplo de línea vertical, la posición Y todavía hacía referencia a una posición de línea de cuadrícula entera; de no haber sido así, veríamos píxeles con la mitad de la cobertura en los extremos.

A pesar de que resulta un tanto difícil empezar a trabajar con los gráficos 2D escalables, si prestas atención a la cuadrícula de píxeles y a la posición de las rutas, te asegurarás de que tus dibujos queden correctos, independientemente de la escala o de otras transformaciones que se tengan que hacer. Una línea vertical de 1.0 de ancho trazada en la posición correcta se convertirá en una línea nítida de 2 píxeles cuando se escale a 2, y aparecerá en la posición correcta.

Un ejemplo de lineCap

La propiedad lineCap determina cómo se dibujan los puntos finales de cada línea. Hay tres posibles valores para esta propiedad y son los siguientes: butt , round y square . De manera predeterminada, esta propiedad se establece a butt .

En este ejemplo, he dibujado tres líneas, cada una con un valor diferente para la propiedad lineCap. También he añadido dos guías para ver las diferencias exactas entre las tres. Cada una de estas líneas empieza y termina exactamente en estas guías.

La línea de la izquierda utiliza la opción predeterminada butt. Te darás cuenta de que está dibujado totalmente nivelado con las guías. La segunda está configurada para que use la opción round. Esto añade un semicírculo hasta el final que tiene un radio la mitad del ancho de la línea. La línea de la derecha utiliza la opción square. Esto añade una caja con un ancho igual y la mitad de la altura del grosor de la línea.

Ver este ejemplo

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');
  var lineCap = ['butt','round','square'];

  // Dibujar guías
  ctx.strokeStyle = '#09f';
  ctx.beginPath();
  ctx.moveTo(10,10);
  ctx.lineTo(140,10);
  ctx.moveTo(10,140);
  ctx.lineTo(140,140);
  ctx.stroke();

  // Dibujar líneas
  ctx.strokeStyle = 'black';
  for (var i=0;i<lineCap.length;i++){
    ctx.lineWidth = 15;
    ctx.lineCap = lineCap[i];
    ctx.beginPath();
    ctx.moveTo(25+i*50,10);
    ctx.lineTo(25+i*50,140);
    ctx.stroke();
  }
}

Un ejemplo de lineJoin

La propiedad lineJoin determina cómo dos líneas conectadas de una forma se unen entre sí. Hay tres posibles valores para esta propiedad: round , bevel y miter . De manera predeterminada esta propiedad se establece en miter .

Una vez más he dibujado tres rutas diferentes, cada una con una configuración de la propiedad lineJoin diferente. La ruta superior utiliza la opción round. Esta configuración redondea las esquinas de una forma. El radio de estas esquinas redondeadas es igual a la anchura de la línea. La segunda línea utiliza la opción bevel y la línea en la parte inferior utiliza la opción miter. Cuando se establecen en miter , las líneas se unen mediante la extensión de los bordes exteriores para conectarse a un solo punto. Esta configuración se efectuará mediante la propiedad miterLimit que se explica a continuación.

Ver este ejemplo

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');
  var lineJoin = ['round','bevel','miter'];
  ctx.lineWidth = 10;
  for (var i=0;i<lineJoin.length;i++){
    ctx.lineJoin = lineJoin[i];
    ctx.beginPath();
    ctx.moveTo(-5,5+i*40);
    ctx.lineTo(35,45+i*40);
    ctx.lineTo(75,5+i*40);
    ctx.lineTo(115,45+i*40);
    ctx.lineTo(155,5+i*40);
    ctx.stroke();
  }
}

Una demostración de la propiedad miterLimit

Como hemos visto en el ejemplo anterior, cuando se unen dos líneas con la opción miter, los bordes exteriores de estas dos líneas se extienden hasta el punto donde se encuentran. Para las líneas que forman un ángulo grande con las demás, este punto no está lejos del punto de conexión interior. Sin embargo, cuando los ángulos entre cada línea disminuyen, la distancia (longitud de miter) entre estos puntos aumenta de manera exponencial.

La propiedad miterLimit determina hasta qué distancia se puede colocar el punto de conexión exterior a partir del punto de conexión interior. Si dos líneas superan este valor, se dibujará una unión biselada.

He hecho una pequeña demostración en la que puedes establecer miterLimit de manera dinámica y ver cómo esto afecta a las formas del lienzo. Las líneas azules muestran donde están el inicio y los puntos finales para cada una de las líneas del diseño en zig-zag.

Vea esta demostración

Degradados

Al igual que cualquier programa de dibujo normal, podemos rellenar y trazar formas mediante degradados lineales y radiales. Creamos un objeto canvasGradient utilizando uno de los métodos siguientes. Usamos este objeto para asignarlo a las propiedades fillStyle o strokeStyle.

createLinearGradient(x1,y1,x2,y2)
createRadialGradient(x1,y1,r1,x2,y2,r2)

El método createLinearGradient toma cuatro argumentos que representan el punto de partida (x1, y1) y el punto final (x2, y2) del degradado.
El método createRadialGradient tiene seis argumentos. Los tres primeros argumentos definen un círculo con las coordenadas (x1, y1) y radio r1 y el segundo, un círculo con las coordenadas (x2, y2) y el radio r2.

var lineargradient = ctx.createLinearGradient(0,0,150,150);
var radialgradient = ctx.createRadialGradient(75,75,0,75,75,100);

Una vez que hemos creado un objeto canvasGradient, podemos asignarle colores utilizando el método addColorStop.

addColorStop(position, color)

Este método toma dos argumentos. El argumento position (posición) debe ser un número entre 0.0 y 1.0 y define la posición relativa de los colores en el degradado. Si se configurara a 0.5, por ejemplo, pondría el color, precisamente, en el centro del degradado. El argumento color debe ser una cadena que represente un color CSS (es decir, #FFF, rgba (0,0,0,1), etc.)

Puedes agregar tantas paradas de color a un degradado como necesites. A continuación se muestra un degradado lineal muy simple de blanco a negro.

var lineargradient = ctx.createLinearGradient(0,0,150,150);
lineargradient.addColorStop(0,'white');
lineargradient.addColorStop(1,'black');

Un ejemplo de createLinearGradient

En este ejemplo, he creado dos degradados diferentes. En el primero, creo el degradado de fondo. Como puedes ver, he asignado dos colores en la misma posición. Lo hacemos así para realizar transiciones de color muy fuertes: en este caso del blanco al verde. Normalmente, no importa en qué orden se definen las paradas de color, pero en este caso especial, sí que importa de manera significativa. Si mantienes la asignación en el orden que deseas que aparezcan, no supondrá un problema.

En el segundo degradado, no asigné el color inicial (en la posición 0.0) ya que no era estrictamente necesario. Asignar el color negro en la posición 0.5 automáticamente convierte en negro el degradado, desde el principio hasta esta parada.

Como puedes ver aquí, tanto la propiedad strokeStyle como la fillStyle pueden aceptar un objeto canvasGradient como entrada válida.

Ver este ejemplo

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

  // Crear degradados
  var lingrad = ctx.createLinearGradient(0,0,0,150);
  lingrad.addColorStop(0, '#00ABEB');
  lingrad.addColorStop(0.5, '#fff');
  //lingrad.addColorStop(0.5, '#26C000');
  //lingrad.addColorStop(1, '#fff');

  var lingrad2 = ctx.createLinearGradient(0,50,0,95);
  lingrad2.addColorStop(0.5, '#000');
  lingrad2.addColorStop(1, 'rgba(0,0,0,0)');

  // asignar degradados a estilos de relleno y trazo
  ctx.fillStyle = lingrad;
  ctx.strokeStyle = lingrad2;
  
  // dibujar formas
  ctx.fillRect(10,10,130,130);
  ctx.strokeRect(50,50,50,50);

}

Un ejemplo de createRadialGradient

En este ejemplo, he definido cuatro degradados radiales diferentes. Como tenemos el control sobre los puntos de inicio y cierre de la degradados, podemos lograr efectos más complejos de lo que normalmente se tienen en degradados radiales 'clásicos' que vemos en, por ejemplo, Photoshop. (Es decir, un degradado con un punto central único donde aquél (el degradado) se expande hacia afuera en forma circular.)

En este caso, he desplazado el punto de partida un poco desde el punto final para lograr un efecto 3D esférico. Es mejor tratar de evitar que los círculos interiores y exteriores se solapen, porque esto da lugar a efectos extraños que son difíciles de predecir.

La última parada de color en cada uno de los cuatro degradados utiliza un color totalmente transparente. Si deseas tener una buena transición de ésta a la parada de color anterior, ambos colores deben ser iguales. Esto no resulta muy evidente a partir del código porque he utilizado dos métodos de color CSS diferentes, excepto en el primer degradado #019F62 = rgba(1,159,98,1)

Ver este ejemplo

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

  // Crear degradados
  var radgrad = ctx.createRadialGradient(45,45,10,52,50,30);
  radgrad.addColorStop(0, '#A7D30C');
  radgrad.addColorStop(0.9, '#019F62');
  radgrad.addColorStop(1, 'rgba(1,159,98,0)');
  
  var radgrad2 = ctx.createRadialGradient(105,105,20,112,120,50);
  radgrad2.addColorStop(0, '#FF5F98');
  radgrad2.addColorStop(0.75, '#FF0188');
  radgrad2.addColorStop(1, 'rgba(255,1,136,0)');

  var radgrad3 = ctx.createRadialGradient(95,15,15,102,20,40);
  radgrad3.addColorStop(0, '#00C9FF');
  radgrad3.addColorStop(0.8, '#00B5E2');
  radgrad3.addColorStop(1, 'rgba(0,201,255,0)');

  var radgrad4 = ctx.createRadialGradient(0,150,50,0,140,90);
  radgrad4.addColorStop(0, '#F4F201');
  radgrad4.addColorStop(0.8, '#E4C700');
  radgrad4.addColorStop(1, 'rgba(228,199,0,0)');
  
  // dibujar formas
  ctx.fillStyle = radgrad4;
  ctx.fillRect(0,0,150,150);
  ctx.fillStyle = radgrad3;
  ctx.fillRect(0,0,150,150);
  ctx.fillStyle = radgrad2;
  ctx.fillRect(0,0,150,150);
  ctx.fillStyle = radgrad;
  ctx.fillRect(0,0,150,150);
}

Diseños

En uno de los ejemplos de la página anterior, he utilizado una serie de bucles para crear un patrón de imágenes. Hay, sin embargo, un método mucho más simple: el método createPattern.

createPattern(image,type)

Este método toma dos argumentos. "Image" es una referencia a un objeto Image o a un elemento canvas diferente. "Type" debe ser una cadena que contenga uno de los siguientes valores: repeat , repeat-x , repeat-y y no-repeat .

Nota : En Firefox 1.5 (Gecko 1.8) no funciona usar un elemento canvas como el argumento Image.

Usamos este método para crear un objeto Pattern que es muy similar a los métodos de degradado que hemos visto anteriormente. Una vez que hayamos creado un patrón, podemos asignarlo a las propiedades fillStyle o strokeStyle.

var img = new Image();
img.src = 'someimage.png';
var ptrn = ctx.createPattern(img,'repeat');

Nota: A diferencia del método drawImage, debes asegurarte de que la imagen que usas se carga antes de llamar a este método o el diseño se dibujará de forma incorrecta.

Nota: Firefox en la actualidad sólo admite la propiedad repeat. Si asignas cualquier otra, no verás ningún cambio.

Un ejemplo de createPattern

En este último ejemplo, he creado un patrón que he asignado a la propiedad fillStyle. Lo único a destacar es el uso del controlador onload de objeto Image. Esto es para asegurarse de que la imagen se carga antes de que se le asigne al patrón.

Ver este ejemplo

Source image

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

  // crear objeto de imagen para usar como diseño
  var img = new Image();
  img.src = 'images/wallpaper.png';
  img.onload = function(){

    // crear diseño
    var ptrn = ctx.createPattern(img,'repeat');
    ctx.fillStyle = ptrn;
    ctx.fillRect(0,0,150,150);

  }
}

Sombras

Gecko 1.9.1 note
(Firefox 3.5 / Thunderbird 3.0 / SeaMonkey 2.0)

Firefox 3.5 (Gecko 1.9.1) introdujo la compatibilidad para las sombras en los lienzos.  El uso de sombras implica sólo cuatro propiedades:

shadowOffsetX = float
shadowOffsetY = float
shadowBlur = float
shadowColor = color

shadowOffsetX y shadowOffsetY indican hasta qué punto se extendería la sombra desde el objeto en las direcciones X e Y, estos valores no se ven afectados por la matriz actual de transformación.  Utiliza valores negativos para que la sombra se extienda hacia arriba o hacia la izquierda, y los valores positivos para que la sombra se extienda hacia abajo o hacia la derecha.  Estos son 0 por defecto.

shadowBlur indica el tamaño del efecto borroso, este valor no se corresponde con un número de píxeles y no se ve afectado por la matriz actual de transformación.  El valor predeterminado es 0.

shadowColor es un valor de color CSS estándar que indica el color del efecto de sombra; de manera predeterminada, es negro totalmente transparente.

Un ejemplo de texto sombreado

Este ejemplo dibuja una cadena de texto con un efecto de sombreado.

Ver este ejemplo

Source image

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

  ctx.shadowOffsetX = 2;
  ctx.shadowOffsetY = 2;
  ctx.shadowBlur = 2;
  ctx.shadowColor = "rgba(0, 0, 0, 0.5)";
 
  ctx.font = "20px Times New Roman";
  ctx.fillStyle = "Black";
  ctx.fillText("Sample String", 5, 30);
}

 

Etiquetas y colaboradores del documento

 Colaboradores en esta página: teoli, StripTM, inma_610
 Última actualización por: teoli,