Manipulando el Canvas HTML5 Usando Konva: Parte 4, Estilizando
Spanish (Español) translation by Rafael Chavarría (you can also view the original English article)
En el segundo tutorial de la serie, aprendiste cómo dibujar algunas formas básicas como rectángulos, círculos, y polígonos regulares usando Konva. El tercer tutorial cubrió cómo puedes usar Konva para dibujar algunas formas complejas como estrellas y aros así como imágenes en el lienzo.
En este tutorial, iremos un paso más allá y aprenderemos cómo aplicar diferente estilizado a formas cambiando sus valores de relleno y trazo. También aprenderás cómo controlar la opacidad de una forma y aplicarle sombras. En las secciones finales, aprenderás cómo usar modos de fusión para especificar como debería lucir el resultado final si se empalman diferentes formas.
Aplicando Relleno y Trazo
Hemos estado usando las propiedades fill y stroke desde el
primer tutorial de la serie. Sin embargo, solo los hemos usado para rellenar
formas con color sólido hasta ahora. También puedes llenar una forma con degradados (tanto lineal
como radial) así como imágenes. Lo mismo va para diferentes trazos aplicados a
una forma.
Hay dos maneras de aplicar un relleno a diferentes formas.
Puedes establecer el valor del relleno usando la propiedad fill cuando una
forma es creada por primera vez en Konva, o puedes usar el método fill() para
aplicar un relleno de manera dinámica en respuesta a algunos eventos como
hover, clic del botón, etc.
Cuando se llena un elemento con un color sólido, puedes
especificar un valor para la propiedad fill y funcionará bien. Cuando uses un
degradado lineal para rellenar el interior de una forma, necesitas especificar
valores válidos para muchas de las propiedades como fillLinearGradientStartPoint,
fillLinearGradientEndPoint, y fillLinearGradientColorStops. Las primeras dos propiedades aceptan objetos que especifican
las coordenadas x y y de los puntos de inicio y fin del degradado. También
puedes especificar los valores x y ya por separado usando las propiedades fillLinearGradientStartPointX,
fillLinearGradientStartPointY, fillLinearGradientEndPointX, y
fillLinearGradientEndPointY.
Los degradados lineales también tienen el mismo conjunto de
propiedades, pero la palabra Linear es reemplazada con Radial. Dos propiedades
adicionales relacionadas con degradados radiales son fillRadialGradientStartRadius
y fillRadialGradientEndRadius.
1 |
var canvasWidth = 600; |
2 |
var canvasHeight = 400; |
3 |
|
4 |
var stage = new Konva.Stage({ |
5 |
container: "example", |
6 |
width: canvasWidth, |
7 |
height: canvasHeight |
8 |
});
|
9 |
|
10 |
var layerA = new Konva.Layer(); |
11 |
|
12 |
var rectA = new Konva.Rect({ |
13 |
x: 25, |
14 |
y: 25, |
15 |
width: 200, |
16 |
height: 150, |
17 |
fillLinearGradientStartPoint: { |
18 |
x: 0, |
19 |
y: 0 |
20 |
},
|
21 |
fillLinearGradientEndPoint: { |
22 |
x: 200, |
23 |
y: 150 |
24 |
},
|
25 |
fillLinearGradientColorStops: [0, 'blue', 1, 'yellow'], |
26 |
stroke: "black" |
27 |
});
|
28 |
|
29 |
var rectB = new Konva.Rect({ |
30 |
x: 375, |
31 |
y: 25, |
32 |
width: 200, |
33 |
height: 150, |
34 |
fillLinearGradientStartPoint: { |
35 |
x: 0, |
36 |
y: 50 |
37 |
},
|
38 |
fillLinearGradientEndPoint: { |
39 |
x: 100, |
40 |
y: -50 |
41 |
},
|
42 |
fillLinearGradientColorStops: [0, 'green', 0.1, 'yellow', 0.5, 'red', 0.9, 'black'], |
43 |
stroke: "black" |
44 |
});
|
45 |
|
46 |
var rectC = new Konva.Rect({ |
47 |
x: 25, |
48 |
y: 200, |
49 |
width: 200, |
50 |
height: 150, |
51 |
fillRadialGradientStartRadius: 0, |
52 |
fillRadialGradientEndRadius: 220, |
53 |
fillRadialGradientColorStops: [0, 'green', 0.5, 'yellow', 0.75, 'red', 0.9, 'black'], |
54 |
stroke: "black" |
55 |
});
|
56 |
|
57 |
var rectD = new Konva.Rect({ |
58 |
x: 375, |
59 |
y: 200, |
60 |
width: 200, |
61 |
height: 150, |
62 |
fillRadialGradientStartRadius: 0, |
63 |
fillRadialGradientEndRadius: 150, |
64 |
fillRadialGradientStartPoint: { |
65 |
x: 100, |
66 |
y: 75 |
67 |
},
|
68 |
fillRadialGradientEndPoint: { |
69 |
x: 100, |
70 |
y: 75 |
71 |
},
|
72 |
fillRadialGradientColorStops: [0, 'blue', 0.5, 'yellow', 0.9, 'green'], |
73 |
stroke: "black" |
74 |
});
|
75 |
|
76 |
layerA.add(rectA, rectB, rectC, rectD); |
77 |
|
78 |
stage.add(layerA); |
Cuando no se especifica, el punto inicial y final de un
degradado radial es asumido para ser 0,0. Por esto es que el degradado radial
en el tercer rectángulo se origina desde la esquina superior izquierda. También recuerda que los puntos de inicio y fin son
especificados relativos a la figura misma.
Al igual que el relleno, puedes establecer el valor de color
y ancho de trazo usando las propiedades stroke y strokewidth cuando una forma
es instanciada primero. También puedes establecer de manera dinámica estos dos
valores usando los métodos stroke() y strokewidth().
Creando Sombras en Konva
Puedes aplicar sombras a cualquier forma creada usando Konva
con la ayuda de cuatro propiedades diferentes llamadas shadowColor,
shadowOffset, shadowBlur, y shadowOpacity. La propiedad shadowOffset acepta un
objeto con componentes x y y como su valor, pero también puedes usar
shadowOffsetX y shadowOffsetY para especificar las coordenadas x y y de forma
separada. También tienes la opción de habilitar y deshabilitar las
sobras para cualquier forma particular usando la propiedad shadowEnabled.
Puedes controlar la opacidad de la forma misma usando la
propiedad opacity. Por favor nota que un objeto completamente transparente no
proyectará una sombra. De manera similar, si has establecido el color fill de una
forma a transparente, solo la sombra de su stroke será generada sobre el lienzo.
1 |
var canvasWidth = 600; |
2 |
var canvasHeight = 400; |
3 |
|
4 |
var stage = new Konva.Stage({ |
5 |
container: "example", |
6 |
width: canvasWidth, |
7 |
height: canvasHeight |
8 |
});
|
9 |
|
10 |
var layerA = new Konva.Layer(); |
11 |
|
12 |
var rectA = new Konva.Rect({ |
13 |
x: 25, |
14 |
y: 25, |
15 |
width: 200, |
16 |
height: 150, |
17 |
cornerRadius: 5, |
18 |
fill: "orange", |
19 |
opacity: 0.5, |
20 |
shadowColor: "black", |
21 |
shadowOffset: { |
22 |
x: -10, |
23 |
y: 10 |
24 |
},
|
25 |
shadowBlur: 10, |
26 |
stroke: "black" |
27 |
});
|
28 |
|
29 |
var starA = new Konva.Star({ |
30 |
x: 400, |
31 |
y: 200, |
32 |
numPoints: 10, |
33 |
innerRadius: 50, |
34 |
outerRadius: 150, |
35 |
fill: "transparent", |
36 |
stroke: "black", |
37 |
strokeWidth: 5, |
38 |
shadowColor: "red", |
39 |
shadowOffset: { |
40 |
x: 5, |
41 |
y: 5 |
42 |
},
|
43 |
shadowBlur: 0 |
44 |
});
|
45 |
|
46 |
layerA.add(rectA, starA); |
47 |
|
48 |
stage.add(layerA); |
Estableciendo la propiedad shadowBlur a 0 hace la sombra tan
afilada como la forma original. Establecer este valor demasiado alto hará que
la sombra pierda su forma original; solo verás un parche oscuro sobre el
lienzo.
Me gustaría notar que también puedes crear sombras de texto
con el mismo conjunto de propiedades una vez que instanciaste un objeto
Konva.Text().
Aplicando Modos de Fusión
Hasta ahora en la serie, cualquier empalme entre formas ocultaba la forma inferior por completo. La única manera de mantener visible la forma inferior fue hacer todas las formas sobre esta parcialmente transparentes.
Algunas veces, podrías querer que el resultado final después del empalme de diferentes formas siga ciertas reglas. Por ejemplo, es posible solo mostrar el color más claro u oscuro en casos en donde las formas se empalman.
Konva te permite especificar algunos valores para determinar
cómo se deberían fusionar los colores de formas empalmadas usando la propiedad globalCompositeOperation.
Puedes leer la documentación en MDN para aprender sobre la propiedad y sus
posibles valores a más detalle.
En el siguiente ejemplo, he aplicado un modo de fusión diferente a cada uno de los rectángulos colocados en la esquina del rectángulo central.
1 |
var canvasWidth = 600; |
2 |
var canvasHeight = 400; |
3 |
|
4 |
var stage = new Konva.Stage({ |
5 |
container: "example", |
6 |
width: canvasWidth, |
7 |
height: canvasHeight |
8 |
});
|
9 |
|
10 |
var layerA = new Konva.Layer(); |
11 |
|
12 |
var rectCenter = new Konva.Rect({ |
13 |
x: 225, |
14 |
y: 125, |
15 |
width: 150, |
16 |
height: 150, |
17 |
fill: "rgb(255, 100, 0)" |
18 |
});
|
19 |
|
20 |
var rectA = new Konva.Rect({ |
21 |
x: 125, |
22 |
y: 25, |
23 |
width: 150, |
24 |
height: 150, |
25 |
fill: "rgb(0, 200, 100)", |
26 |
globalCompositeOperation: "lighten" |
27 |
});
|
28 |
|
29 |
var rectB = new Konva.Rect({ |
30 |
x: 325, |
31 |
y: 25, |
32 |
width: 150, |
33 |
height: 150, |
34 |
fill: "rgb(0, 200, 100)", |
35 |
globalCompositeOperation: "darken" |
36 |
});
|
37 |
|
38 |
var rectC = new Konva.Rect({ |
39 |
x: 125, |
40 |
y: 225, |
41 |
width: 150, |
42 |
height: 150, |
43 |
fill: "rgb(0, 200, 100)", |
44 |
globalCompositeOperation: "hue" |
45 |
});
|
46 |
|
47 |
var rectD = new Konva.Rect({ |
48 |
x: 325, |
49 |
y: 225, |
50 |
width: 150, |
51 |
height: 150, |
52 |
fill: "rgb(0, 255, 0)", |
53 |
globalCompositeOperation: "xor" |
54 |
});
|
55 |
|
56 |
layerA.add(rectCenter, rectA, rectB, rectC, rectD); |
57 |
|
58 |
stage.add(layerA); |
El color del rectángulo de encima es rgb(0, 200, 100), y el color del rectángulo central es rgb(255, 100, 0). Cuando el modo de fusión lighten es aplicado, los componentes rgb de ambos colores son comparados de manera individual, y los valores más altos para cada componente son usados para obtener el valor final. En nuestro caso, el color final de la esquina superior izquierda se vuelve rgb(255, 200, 100).
Cuando el modo de fusión darken es aplicado, los componentes
rgb de ambos colores son comparados de manera individual, y los valores más
bajos para cada componente son usados para obtener el color final. En nuestro
caso, el color final para la esquina superior derecha se vuelve rgb(0, 100, 0).
Cuando el modo de fusión hue es aplicado, la luminosidad y
croma del color inferior son combinados con el tono del color de encima. Es por esto que el color final aún permanece verde pero se
vuelve más claro. Cuando el modo de fusión xor es aplicado, el color final se
vuelve transparente en todos los lugares de empalme.
Ideas Finales
En este tutorial, aprendimos cómo rellenar una forma con
degradados lineales o radiales en lugar de colores sólidos. También aprendimos
cómo aplicar sombras a diferentes formas y hacerlas parcialmente transparentes
usando la propiedad opacity. La sección final te mostró cómo usar modos de fusión para
poder cambiar el color final después de que dos formas se empalmen.
Si tienes alguna pregunta relacionada con este tutorial, por favor déjame saber en los comentarios. El siguiente tutorial de esta serie te enseñará cómo conectar eventos a diferentes formas en Konva.



