In this topic, we will talk about how to apply styling and coloring in the JavaScript Canvas and how to produce outlined and filled shapes and also applying single colors and using linear and circular gradients.
In the previous lesson, we learned about how to use the HTML Canvas, as well as how to use it in 2D drawing, as well as how to use the common functions of drawing, such as drawing rectangles, drawing straight lines and showing text and images in canvas.
Let’s continue in this article by applying colors to the shapes we have drawn in the previous lesson. There are two properties we can use which are the fillStyle, and strokeStyle. fillStyle set the style used when filling shapes. strokeStyle set the style for outlined shapes.
fillStyle = color strokeStyle = color
The color value can be a CSS color which is the color name or the hexadecimal code or the rgb() value of the color. The following is a valid examples:
context.fillStyle = 'blue'; // color name context.fillStyle = '#0d0388'; // hexidecimal code context.fillStyle = 'rgb(21, 0, 123)'; // rgb value context.fillStyle = 'rgba(255, 165, 0, 1)
'; // rgba value context.strokeStyle = 'red'; // color name context.strokeStyle = '#0d0388'; // hexidecimal code context.strokeStyle = 'rgb(21, 0, 123)'; // rgb value context.strokeStyle = 'rgba(255, 165, 0, 1)
';Â // rgba value
The color can also be a gradient object, or pattern object which we will discover later.
Let’s see an example for fillStyle, we will draw some rectangles and color it with different color:
context.fillStyle = 'red'; context.fillRect(10, 10, 370, 60); context.fillStyle = 'blue'; context.fillRect(10, 80, 370, 60); context.fillStyle = 'green'; context.fillRect(10, 150, 370, 60);
In this example we displayed three rectangles, each have it’s own color. So i called fillStyle before each rectangle, if you want the three rectangles have the same color, just call fillStyle once because setting fillStyle will affect all the subsequent shapes.
Let’s see another example for strokeStyle property. Note that strokeStyle used only for outlined shapes like lines, paths, arcs.
context.beginPath(); context.arc(100, 300, 30, 0, 380, 0); context.strokeStyle = 'rgb(0,255,255)'; context.stroke(); context.beginPath(); context.arc(170, 300, 30, 0, 380, 0); context.strokeStyle = 'rgb(128,0,0)'; context.stroke(); context.beginPath(); context.arc(240, 300, 30, 0, 380, 0); context.strokeStyle = 'rgb(0,128,128)'; context.stroke(); context.beginPath(); context.strokeStyle = 'rgb(0,128,128)'; context.moveTo(30, 120); context.lineTo(120, 30); context.lineTo(200, 120); context.closePath(); context.stroke();
In this example i displayed three outlined circles and a triangle made of paths and applied the strokeStyle property to each of them.
We can also display make the circles and the triangle filled by replacing stroke() and strokeStyle by fill() and fillStyle as shown:
context.beginPath(); context.fillStyle = 'rgb(0,128,128)'; context.moveTo(30, 120); context.lineTo(120, 30); context.lineTo(200, 120); context.closePath(); context.fill();
What about setting the transparency of the color? you can accomplish this in two ways either by passing rgba(R, G, B, A) color value to strokeStyle or fillStyle or by setting the globalAlpha property.
If you set the globalAlpha property all future shapes will be drawn using the transparency value in this property
context.globalAlpha = transparencyValue
The transparency value must be between 0.0 (fully transparent) to 1.0 (fully opaque). This value is 1.0 (fully opaque) by default.
Let’s add the globalAlpha = 0.5 to the previous example before the beginPath() function like so:
context.globalAlpha = 0.5;
Now all the shapes will be transparent.
If you want to set the transparent value per shape you can assign the rgba() value to fillStyle or strokeStyle properties. The rgba()
function is similar to the rgb()
function but it has one extra parameter. The last parameter sets the transparency value of this particular color.
For example let’s make the previous triangle as transparent like so:
context.beginPath(); context.fillStyle = 'rgb(0,128,128, 0.5)'; context.moveTo(30, 120); context.lineTo(120, 30); context.lineTo(200, 120); context.closePath(); context.fill();
Coloring With Gradient
The gradient is composed of group of colors, you may have saw gradients before in programs such as Photoshop. There are two common types of gradients the linear and circular gradients. The linear gradient is such type that have a start point and end point. The circular one is represent two circles, one with its center at (x1
, y1
) and a radius of r1
, and the other with its center at (x2
, y2
) with a radius of r2.
To create linear gradient we can use createLinearGradient(x1, y1, x2, y2) function where (x1,y1) represent the starting point and (x2, y2) represent the end point. To create circular gradient we can use createRadialGradient(x1, y1, r1, x2, y2, r2) where (x1, y1) represent the circle one center, r1 represent circle one radius, (x2, y2) represent circle two circle, r2 represent circle two radius.
Both functions return a CanvasGradient object.
Steps To create a gradient:
- Use createLinearGradient() or createRadialGradient() to create a gradient object.
- Once you create the gradient object assign colors by using CanvasGradient.addColorStop(position, color).
- You can assign as many colors as you want by addColorStop(position, color).
- Then assign the gradient object to fillStyle or strokeStyle properties. Â
Let’s see this example where i created a linear gradient to display a rectangle with gradient color:
let linearGradient = context.createLinearGradient(0, 0, 370, 0); linearGradient.addColorStop(0, 'white'); linearGradient.addColorStop(0.5, 'green'); linearGradient.addColorStop(1, 'red'); context.fillStyle = linearGradient; context.fillRect(10, 10, 370, 200);
In this example i am displaying a gradient rectangle having three colors starting from white color and ending with the red color. the addColorStop(position, color) takes the position which is a number between 0 and 1.0 specifying the color position in the gradient. Once i created the linearGradient object i assigned it to context.fillStyle.
Let’s add more colors to gradient:
linearGradient.addColorStop(0, 'white'); linearGradient.addColorStop(0.3, 'blue'); linearGradient.addColorStop(0.5, 'green'); linearGradient.addColorStop(0.7, 'yellow'); linearGradient.addColorStop(0.9, 'pink'); linearGradient.addColorStop(1, 'red');
Another example with outlined rectangle:
let linearGradient2 = context.createLinearGradient(0, 0, 370, 0); linearGradient2.addColorStop(0, '#000'); linearGradient2.addColorStop(0.3, 'blue'); linearGradient2.addColorStop(0.5, 'green'); linearGradient2.addColorStop(0.7, 'yellow'); linearGradient2.addColorStop(0.9, 'pink'); linearGradient2.addColorStop(1, 'red'); context.strokeStyle = linearGradient2; context.strokeRect(10, 220, 370, 100);
Here i have done the same thing but instead i used strokeStyle property.
Radial gradient example:
let circularGradient = context.createRadialGradient(50, 50, 30, 50, 80, 30); circularGradient.addColorStop(0, 'white'); circularGradient.addColorStop(0.3, 'blue'); circularGradient.addColorStop(0.5, 'green'); circularGradient.addColorStop(0.7, 'yellow'); circularGradient.addColorStop(0.9, 'pink'); circularGradient.addColorStop(1, 'red'); context.fillStyle = circularGradient; context.fillRect(10, 10, 370, 200);
Â
Coloring With A Pattern
Like the gradient type the pattern is used in graphics processing software like Photoshop. A pattern is created using an image which get repeated in someway. To create a pattern we can use createPattern(image, type) function where the image parameter can be an image instance created using javascript Image() constructor or it can be a reference to an html <img /> tag.
The type parameter specifies how to create the pattern, and it can be one of the following:
- repeat: Tiles the image in both vertical and horizontal directions.
- repeat-x: Tiles the image horizontally.
- repeat-y: Tiles the image vertically.
- no-repeat: Doesn’t tile the image. It’s used only once
The createPattern() function return CanvasPattern object, once created we need to assign this pattern to fillStyle or strokeStyle properties just like gradients.
Let’s see an example to create a rectangle and fill it using createPattern()
let img = new Image(20, 20); img.src = './pattern.jpg'; img.addEventListener('load', function() { let pattern = context.createPattern(img, 'repeat'); context.fillStyle = pattern; context.fillRect(0, 0, 370, 200); }, false);
Like the drawImage() function we already saw in the previous lesson you must listen on the load callback in the image and then fill and create the rectangle otherwise the image will not be loaded in the pattern.
We can use the pattern also in this example to create a frame using strokeStyle and strokeRect:
let img = new Image(20, 20); img.src = './pattern.jpg'; img.addEventListener('load', function() { let pattern = context.createPattern(img, 'repeat'); context.lineWidth = 10; context.strokeStyle = pattern; context.strokeRect(10, 10, 370, 200); }, false);
Line Properties
There are some properties when working with lines, strokeRect and strokeText some of these:
lineWidth = value
Sets the thickness of the lines drawn.
context.lineWidth = 10; context.beginPath(); context.moveTo(20, 20); context.lineTo(130, 130); context.stroke();
lineCap = type
Sets the appearance of line endings. Possible values are “butt”, “round”, “square”.
context.lineCap = "round";
lineJoin = type
Sets the appearance when two or more lines joins in the same point. Possible values are “bevel”, “round”, “miter”.
round: Rounds off the corners of a shape.
bevel: Fills an additional triangular area between the common endpoint of connected segments.
miter: Connected segments are joined by extending their outside edges to connect at a single point
You can experiment with three types in the below example:
context.lineWidth = 10; context.lineJoin = "round"; context.beginPath(); context.moveTo(20, 20); context.lineTo(130, 130); context.lineTo(280, 20); context.stroke();
setLineDash(segments)
If you want to create a dashed line, this function sets the line dash pattern used when stroking lines. The segments parameter specify distances to alternately draw a line and a gap (in coordinate space units). If the number of elements in the array is odd, the elements of the array get copied and concatenated. If you supply empty array the line return to be solid.
For example in the previous example if you specify:
context.setLineDash([5, 15]);
This array has two values 5 and 15. The first value 5 represent the dash length where as the second value 15 is the empty gap between each dash.
getLineDash()
Return the line dash array previously by setLineDash() function.Â
In the previous example:
console.log(context.getLineDash()); // (2)Â [5, 15]
lineDashOffset = value
Sets the line dash offset. default value is 0.0
context.lineDashOffset = 5;