The HTML <canvas> element provides various features such as drawing shapes and animations that can be used to create games and other applications. In this writing, we will see some of its attributes and how to use them and I will also introduce some useful tricks when working with the canvas such as dynamic sizing and the drawing application made with the canvas.
List of Contents
- Initialization
- Sizing
- Using Canvas
- Other Features
-
Styles
- ▶ strokeStyle = "color"
- ▶ fillStyle = "color"
- ▶ lineWidth = size
- ▶ lineCap = "type"
- ▶ lineJoin = "type"
- ▶ setLineDash([lineWith, spaceWidth,...])
- ▶ lineDashOffset = offsetValue
- ▶ createLinearGradient(xStart, yStart, xEnd, yEnd)
- ▶ createRadialGradient(xStart, yStart, radiusStart, xEnd, yEnd, radiusEnd)
- ▶ quadraticCurveTo(xCurve, yCurve, xEnd, yEnd)
- Canvas Application - Drawing
The canvas element can be created either with HTML or JavaScript. However, we need the Canvas API to draw things on the canvas, so drawing can only be done with JavaScript.
Add the tag in the HTML to use the canvas
<body>
<canvas width="1000" height="1000"></canvas>
</body>
Or, as mentioned above, create a canvas in JavaScript using the DOM
const canvasEl = document.createElement('canvas')
document.body.appendChild(canvasEl)
Initialization
One more thing we need to draw things on the canvas is the context. A context is the collection of the implementation methods we can choose from. To mention a few we have "2d", "webgl", "webgl2", and "bitmaprenderer". In this writing, we will use the "2d" context as it is simple and most heavily used. Note that each canvas can only have one context.
▶ getContext("context")
<!-- index.html -->
<body>
<canvas width="800" height="600"></canvas>
</body>
width, height, mozOpaque, and mozPrintCallback are the only attributes a canvas can have other than the global attributes. For the width and height, 300px and 150px are default values. It is better to use the attribute rather than the CSS styles to set the size because there is a difference between the two values (I will elaborate on this subject below).
※ mozOpaque (deprecated) is the option to control the opacity of a canvas that can only be used for Mozilla-based browsers. This feature is not used often as there is an easier way to do the same thing with canvas configuration options.
※ mozPrintCallback is a callback function that is only supported by the Firefox browser Nightly (FF18) version. Its main feature is to run the code when all the pages are ready for printing not whenever a page is ready. It is in the experiment phase and not one of the standard features yet (Related: A New Way to Control Printing Output | Mozilla Labs).
/* index.js */
const canvas = document.querySelector('canvas')
const cv = canvas.getContext('2d')
// ※ shortcut
const cv = document.querySelector('canvas').getContext('2d')
Context configurations options:
- alpha: controls the opacity
/* index.js */
const canvas = document.querySelector('canvas')
const cv = canvas.getContext('2d', {
alpha: true
})
/* main.css */
canvas {
border: 4px solid #000;
margin: auto;
display: block;
}
Sizing
It is recommended to set the size of a canvas in the element not with CSS. Because the units in the canvas attributes for the size are slightly different from the size attributes in the CSS. So images will be distorted if you set the size using CSS and try to draw something.
<!-- index.html -->
<body>
<canvas width="300" height="300"></canvas>
<canvas class="canvas-css"></canvas>
</body>
/* index.js */
const canvas = document.querySelector('canvas')
const canvasCSS = document.querySelector('.canvas-css')
const cv = canvas.getContext('2d')
const cv2 = canvasCSS.getContext('2d')
cv.beginPath()
cv.moveTo(0, 0)
cv.lineTo(100, 100)
cv.stroke()
cv2.beginPath()
cv2.moveTo(0, 0)
cv2.lineTo(100, 100)
cv2.stroke()
/* main.css */
body {
display: flex;
}
canvas {
border: 4px solid #000;
margin: auto;
display: block;
}
.canvas-css {
height: 300px;
width: 300px;
}
Dynamic Sizing
Using Canvas
Now, let's see how we can draw on the canvas
There are two basic syntaxes:
- Canvas can use a shape and line to draw and 'fill' is used for the shapes and 'stroke' is used for the lines
- The first two parameters represent the coordinate, x, and y (The measuring point of a shape is the top left corner of the shape).
Shapes
▶ fillRect(x, y, width, height)
Draws a rectangular
cv.fillStyle = 'yellow' // 색지정
cv.fillRect(60, 60, 200, 200)
▶ strokeRect(x, y, width, height)
Draws the border of a rectangular.
cv.strokeStyle = 'red'
cv.strokeRect(60, 60, 200, 200)
▶ clearRect(x, y, width, height)
Clears everything in the scope specified (like an eraser).
cv.fillStyle = 'yellow'
cv.fillRect(60, 60, 200, 200)
cv.clearRect(60, 60, 100, 100)
cv.strokeStyle = 'red'
cv.strokeRect(60, 60, 200, 200)
Lines
▶ stoke()
cv.lineTo(110, 110)
cv.lineTo(10, 110)
cv.lineTo(10, 10)
cv.stroke()
▶ fill()
cv.lineTo(110, 110)
cv.lineTo(10, 110)
cv.lineTo(10, 10)
cv.fill()
▶ beginPath()
Begins a new line
cv.beginPath()
cv.strokeStyle = 'red'
cv.moveTo(10, 10) // 시작점
cv.lineTo(110, 210)
cv.stroke()
cv.beginPath()
cv.strokeStyle = 'green'
cv.moveTo(10, 10) // 시작점
cv.lineTo(110, 110)
cv.stroke()
▶ arc(x, y, radius, startingAngle, endingAngle, countClockwise)
For the circle, unlike rectangular the measuring point for the coordinate of a circle is the center of the circle.
cv.beginPath()
cv.arc(150, 150, 100, 0, Math.PI / 3);
cv.stroke();
By default, it is drawn clockwise. Set the 'counterclockwise' parameter to 'true' to draw counter clock-wise.
cv.beginPath()
cv.arc(150, 150, 100, 0, Math.PI / 3, true);
cv.stroke();
Fonts
cv.font = "200px Sans-serif" //font = "<fontSize> <fontFamily>"
cv.strokeText("Font stroke", 60, 60) //strokeText("Text", x, y) / fillText("Text", x, y)
cv.font = "200px Sans-serif"
cv.fillText("Font fill", 30, 30)
Other Features
▶ toBlob(callbackFunction, "type", quality)
This converts the image to a Blob object. The second parameter is the format and the default value is "image/png". The third parameter is the quality of the image and the value can be set between 0 ~ 1.
<!-- index.html -->
<body>
<canvas width="200" height="200"></canvas>
</body>
/* index.js */
const canvas = document.querySelector('canvas')
const cv = canvas.getContext('2d')
cv.beginPath()
cv.quadraticCurveTo(0, 10, 100, 100)
cv.stroke()
canvas.toBlob((blob) => {
const newImg = document.createElement('img');
const url = URL.createObjectURL(blob);
newImg.onload = () => {
URL.revokeObjectURL(url);
};
newImg.src = url;
newImg.style.border = '1px solid red'; //구분을 위해 사용
document.body.appendChild(newImg);
}, "image/jpg", 1);
/* main.css */
body {
display: flex;
}
canvas {
border: 4px solid #000;
margin: auto;
display: block;
}
.canvas-css {
height: 300px;
width: 300px;
}
▶ toDataURL("type", quality)
This returns the image path and can be used for downloading the images. The first parameter is the format and the default value is "image/png". The second parameter is the quality of the image and the value can be set between 0 ~ 1.
<!-- index.html -->
<body>
<canvas width="1000" height="1000"></canvas>
</body>
/* index.js */
console.log(canvas.toDataURL())
Styles
<p id="style-stroke" style="color: #333333; text-align: justify;" data-ke-size="size16"><b>▶ strokeStyle = "color"</b></p>
/* index.js */
cv.strokeStyle = "red"
cv.lineTo(110, 220)
cv.lineTo(210, 320)
cv.stroke()
▶ fillStyle = "color"
/* index.js */
cv.fillStyle = "yellow"
cv.fillRect(0, 0, 100, 100)
▶ lineWidth = size
/* index.js */
cv.lineWidth = 300
cv.lineTo(110, 220)
cv.lineTo(210, 320)
cv.stroke()
▶ lineCap = "type"
Defines the shape of the end of a line. Some of the options are "butt", "round", and "square"
/* index.js */
cv.strokeStyle = "red"
cv.lineWidth = 130
cv.beginPath()
cv.lineCap = "butt"
cv.moveTo(110, 220)
cv.lineTo(210, 320)
cv.stroke()
cv.beginPath()
cv.lineCap = "round"
cv.moveTo(410, 220)
cv.lineTo(510, 320)
cv.stroke()
cv.beginPath()
cv.lineCap = "square"
cv.moveTo(710, 220)
cv.lineTo(810, 320)
cv.stroke()
▶ lineJoin = "type"
Defines the shape of the point where lines meet. Some of the options are "round", "bevel", and "miter"
/* index.js */
cv.strokeStyle = "red"
cv.lineWidth = 30
cv.beginPath()
cv.lineJoin = "round"
cv.moveTo(110, 220)
cv.lineTo(210, 320)
cv.lineTo(210, 320)
cv.lineTo(300, 220)
cv.stroke()
cv.beginPath()
cv.lineJoin = "bevel"
cv.moveTo(410, 220)
cv.lineTo(510, 320)
cv.lineTo(510, 320)
cv.lineTo(600, 220)
cv.stroke()
cv.beginPath()
cv.lineJoin = "miter"
cv.moveTo(710, 220)
cv.lineTo(810, 320)
cv.lineTo(810, 320)
cv.lineTo(900, 220)
cv.stroke()
▶ setLineDash([lineWith, spaceWidth,...])
/* index.js */
cv.strokeStyle = "red"
cv.beginPath()
cv.setLineDash([10, 20, 5])
cv.moveTo(110, 220)
cv.lineTo(410, 220)
cv.stroke()
▶ lineDashOffset = offsetValue
Moves the dots by the numbers specified without changing the length of a line
/* index.js */
cv.strokeStyle = "red"
cv.beginPath()
cv.setLineDash([30, 20, 5, 10, 2, 22])
cv.moveTo(110, 220)
cv.lineTo(810, 220)
cv.stroke()
cv.strokeStyle = "green"
cv.beginPath()
cv.setLineDash([30, 20, 5, 10, 2, 22])
cv.lineDashOffset = 130
cv.moveTo(110, 250)
cv.lineTo(810, 250)
cv.stroke()
▶ createLinearGradient(xStart, yStart, xEnd, yEnd)
Sets the linear gradient. To use this, first set the coordinate and the size. Then use the 'addColorStop(location, color) to set the color and the location. The values for the first parameter for the 'addColorStop' is between 0 (start) and 1 (end).
/* index.js */
let grad = cv.createLinearGradient(0, 0, 200, 0)
grad.addColorStop(0, 'red')
grad.addColorStop(1, 'blue')
cv.fillStyle = grad
cv.fillRect(60, 60, 900, 200)
▶ createRadialGradient(xStart, yStart, radiusStart, xEnd, yEnd, radiusEnd)
Sets the radial gradient. To use this, first set the coordinate and the size. Then use the 'addColorStop(location, color) to set the color and the location. The values for the first parameter for the 'addColorStop' is between 0 (start) and 1 (end).
/* index.js */
let gradC = cv.createRadialGradient(150, 150, 10, 290, 160, 280)
gradC.addColorStop(0, 'red')
gradC.addColorStop(1, 'blue')
cv.fillStyle = gradC
cv.fillRect(60, 60, 900, 200)
▶ quadraticCurveTo(xCurve, yCurve, xEnd, yEnd)
/* index.js */
const canvas = document.querySelector('canvas')
const cv = canvas.getContext('2d')
cv.beginPath();
cv.moveTo(20, 110);
cv.quadraticCurveTo(230, 450, 650, 20);
cv.stroke();
Canvas Application - Drawing
We explored the canvas in this writing and I hope it was helpful.
References
Canvas API - Web APIs | MDN (mozilla.org)
Bézier curve - MDN Web Docs Glossary: Definitions of Web-related terms | MDN (mozilla.org)
캔버스 동적크기
https://stackoverflow.com/questions/1664785/resize-html5-canvas-to-fit-window
https://stackoverflow.com/questions/26670810/why-we-cant-set-width-and-height-for-canvas-using-css
'Frontend > JavaScript' 카테고리의 다른 글
NPM - Nodemon (0) | 2023.12.15 |
---|---|
Drag and Drop (1) | 2023.07.05 |
JavaScript Module - Button Ripple Effect (1) | 2023.07.03 |
NPM - JSON Server (0) | 2023.05.22 |
JavaScript Module - Text Wave Effect (2) | 2023.04.05 |