-
-
Save jonurry/03ba3627bd6d7b7e97d69fdec92d1e5a to your computer and use it in GitHub Desktop.
<canvas width="600" height="200"></canvas> | |
<script> | |
let cx = document.querySelector("canvas").getContext("2d"); | |
cx.clearRect(0, 0, 600, 200); | |
const drawTrapezoid = (cx, x, y, width, height, indent) => { | |
cx.beginPath(); | |
cx.moveTo(x + indent, y); | |
cx.lineTo(x - indent + width, y); | |
cx.lineTo(x + width, y + height); | |
cx.lineTo(x, y + height); | |
cx.closePath(); | |
cx.stroke(); | |
} | |
const drawDiamond = (cx, x, y, side, fill) => { | |
cx.save(); | |
cx.fillStyle = fill; | |
cx.translate(x + side / 2, y + side / 2); | |
cx.rotate(Math.PI / 4); | |
cx.translate(-x - side / 2, -y - side / 2); | |
cx.fillRect(x, y, side, side); | |
cx.restore(); | |
} | |
const drawZigZag = (cx, x, y, width, height, num) => { | |
cx.beginPath(); | |
cx.moveTo(x, y); | |
let inc = height / num; | |
for (let i = 0; i < num; i++) { | |
let offset = y + (i * inc); | |
cx.lineTo(x + width, offset + (inc / 2)); | |
cx.lineTo(x, offset + inc); | |
} | |
cx.stroke(); | |
} | |
const drawSpiral = (cx, x, y, width, segments) => { | |
cx.beginPath(); | |
cx.moveTo(x + width / 2, y + width / 2); | |
let inc = Math.pow(Math.PI, 2) / segments; | |
let angle = 0; | |
for (let i = 0; i < segments; i++) { | |
let points = []; | |
angle += inc; | |
points[0] = Math.cos(angle); | |
points[1] = Math.sin(angle); | |
angle += inc; | |
points[2] = Math.cos(angle); | |
points[3] = Math.sin(angle); | |
points = points.map(x => ((x * i) + width) / 2); | |
cx.lineTo(x + points[0], y + points[1]); | |
cx.lineTo(x + points[2], y + points[3]); | |
} | |
cx.stroke(); | |
} | |
const drawStar = (cx, x, y, width, points) => { | |
let halfWidth = width / 2; | |
let xCentre = x + halfWidth; | |
let yCentre = y + halfWidth; | |
let inc = 2 * Math.PI / points; | |
let angle = 0; | |
cx.beginPath(); | |
cx.moveTo(x + width, y + width / 2); | |
for (let i = 0; i < points; i++) { | |
angle += inc; | |
cx.quadraticCurveTo(xCentre, yCentre, xCentre + Math.cos(angle) * halfWidth, yCentre + Math.sin(angle) * halfWidth); | |
} | |
cx.fillStyle = 'orange'; | |
cx.fill(); | |
} | |
drawTrapezoid(cx, 0, 30, 80, 40, 20); | |
drawDiamond(cx, 100, 25, 50, 'red'); | |
drawZigZag(cx, 180, 0, 100, 100, 6); | |
drawSpiral(cx, 300, 0, 100, 100); | |
drawStar(cx, 420, 0, 100, 8); | |
</script> |
Hints
The trapezoid (1) is easiest to draw using a path. Pick suitable centre coordinates and add each of the four corners around that.
The diamond (2) can be drawn the straightforward way, with a path, or the interesting way, with a rotate transformation. To use rotation, you will have to apply a trick similar to what we did in the flipHorizontally
function. Because you want to rotate
around the centre of your rectangle and not around the point (0,0), you must first translate
to there, then rotate, and then translate
back.
Make sure you reset the transformation after drawing any shape that creates one.
For the zigzag (3) it becomes impractical to write a new call to lineTo
for each line segment. Instead, you should use a loop. You can have each iteration draw either two line segments (right and then left again) or one, in which case you must use the evenness (% 2
) of the loop index to determine whether to go left or right.
You’ll also need a loop for the spiral (4). If you draw a series of points, with each point moving further along a circle around the spiral’s centre, you get a circle. If, during the loop, you vary the radius of the circle on which you are putting the current point and go around more than once, the result is a spiral.
The star (5) depicted is built out of quadraticCurveTo
lines. You could also draw one with straight lines. Divide a circle into eight pieces for a star with eight points, or however many pieces you want. Draw lines between these points, making them curve toward the centre of the star. With quadraticCurveTo
, you can use the centre as the control point.
Drawing On Canvas
17.1 Shapes
Write a program that draws the following shapes on a canvas:
When drawing the last two, you may want to refer to the explanation of
Math.cos
andMath.sin
in Chapter 14, which describes how to get coordinates on a circle using these functions.I recommend creating a function for each shape. Pass the position, and optionally other properties, such as the size or the number of points, as parameters. The alternative, which is to hard-code numbers all over your code, tends to make the code needlessly hard to read and modify.