Drawing Multiple Pieces
📝 We continue in the Speedy Chef project folder throughout this section.
Create the pepperoni co-ordinates
We have the pepperoni, ham, and pineapple ingredients left to draw. These involve drawing multiple pieces at different locations. As you would expect, a little more code is involved, but most of which we have already covered.

Starting with pepperoni. For each piece, we need an x and y location which we can store into an array. These values are random, you can play around with them if you would like:
case 'PEPPERONI':
const pepperoniPositions = [
// each array is a piece of pepperoni, x and y
[78, 62],
[118, 74],
[147, 57],
[116, 134],
[125, 190],
[162, 165],
[190, 85],
[192, 142],
[150, 115],
[76, 95],
[80, 190],
[61, 135],
];
break;
Looping over our array
A piece of pepperoni is just a small circle. We know how to use arc
to do this. But the difference is we need to create many, and this is where a loop comes in:
const pepperoniPositions = [
// each array is a piece of pepperoni, x and y
[78, 62],
[118, 74],
[147, 57],
[116, 134],
[125, 190],
[162, 165],
[190, 85],
[192, 142],
[150, 115],
[76, 95],
[80, 190],
[61, 135],
];
// loop through the pepperoniPositions array:
pepperoniPositions.forEach(function (piece) {
ctx.beginPath();
// x and y locations of each piece, radius, start angle, end angle
ctx.arc(piece[0], piece[1], 10, 0, Math.PI * 2);
ctx.fillStyle = '#bd3611';
ctx.fill();
});
break;
Try this our by clicking on the pepperoni ingredient in the kitchen when the game has started!
Drawing ham pieces
Next, onto the ham. Starting with the locations array:
case 'HAM':
const hamPositions = [
[81, 62],
[108, 74],
[147, 47],
[130, 124],
[125, 160],
[159, 145],
[197, 82],
[202, 132],
[158, 90],
[86, 95],
[90, 140],
[105, 135],
];
break;
Loop over each ham position, this time, the drawing will be rectangles rather than circles:
case "HAM":
const hamPositions = [
[81, 62],
[108, 74],
[147, 47],
[130, 124],
[125, 160],
[159, 145],
[197, 82],
[202, 132],
[158, 90],
[86, 95],
[90, 140],
[105, 135],
];
// loop though hamPositions and create a rectangle for each piece
hamPositions.forEach(function (piece) {
ctx.fillStyle = "#f58c8c";
ctx.fillRect(piece[0], piece[1], 8, 32);
});
break;
Random rotation with the rotate()
method
Try this out and you will notice that all pieces of ham are at the same angle. Let’s mix up the angle a little for each one, and we do this with rotate:
hamPositions.forEach(function (piece) {
ctx.fillStyle = '#f58c8c';
// add the rotate method:
ctx.rotate();
ctx.fillRect(piece[0], piece[1], 8, 32);
});
The rotational value is in radians not degrees. We can convert to degrees like this:
// 5= number of degrees
ctx.rotate(5 * Math.PI / 180);
Hard coding degrees is not ideal, it would be better as a random number, using math.random()
:
ctx.rotate(Math.random() * Math.PI / 180);
This works but there is only a tiny rotation since math.random
is a small number. We can multiply this by 2 to increase the rotation:
ctx.rotate((Math.random() * 2 * Math.PI) / 180);
You can play around with this value if you would like a different angle.
Drawing pineapple pieces
Finally, we have the pineapple:
case 'PINEAPPLE':
const pineapplePositions = [
[81, 62],
[108, 74],
[147, 47],
[130, 124],
[125, 160],
[159, 145],
[197, 82],
[202, 132],
[158, 93],
[86, 95],
[90, 145],
[105, 140],
];
pineapplePositions.forEach(function (piece) {
ctx.fillStyle = '#ebe534';
ctx.rotate((Math.random() * 2 * Math.PI) / 180);
ctx.fillRect(piece[0], piece[1], 12, 18);
});
break;
All of this appears to work fine, but we do have a small issue. And this is when we use multiple ingredients with rotation values.
You will see if we add all the ingredients, the rotation may move the ingredients off the pizza. This happens because of the rotation transform.
When we rotate the canvas, we rotate from the canvas origin, which is 0,0, or the top left. If we add multiple rotations, we are adding onto the previous rotation value, rather than the canvas origin.
Reset the canvas origin using setTransform
We can fix this by resetting the origin before we add each ingredient, using the setTransform
method.
The setTransform
method takes in six values which set the scaling, skewing, and translation values. Add this at the beginning of the makePizza
function:
function makePizza(ingredient) {
// horizontal scaling (1= no scaling, original size)
// vertical skewing- nothing to reset
// horizontal skewing- nothing to reset
// vertical scaling (1= no scaling, original size)
// horizontal translation- set back to zero
// vertical translation- set back to zero
ctx.setTransform(1, 0, 0, 1, 0, 0);
//...
This will now reset our transform before each new ingredient is added.