[JavaScript30] ๐ 08. FUN WITH HTML5 CANVAS
08. ๐ FUN WITH HTML5 CANVAS
HTML์ canvas๋ฅผ ์ด์ฉํด ๊ฐ์ข
ํจ๊ณผ๋ฅผ ๋ฃ์ด๋ด.
์ด๊ธฐ์ฝ๋
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>HTML5 Canvas</title>
</head>
<body>
<canvas id="draw" width="800" height="800"></canvas>
</body>
<style>
html, body{
margin: 0;
}
</style>
</html>
๐ ์๊ฒ๋ ๊ฒ
๐ canvas
-
const ctx = canvas.getContext('2d');
- ์บ๋ฒ์ค์ ๋๋ก์ ์ปจํ ์คํธ๋ฅผ ๋ฐํํจ. 2d์ธ๊ฒฝ์ฐ 2d๋ฅผ ์์ฑ.
webgl
|experimental-webgl
: 3์ฐจ์ ๋ ๋๋ง ์ปจํ ์คํธwebg2
: 3์ฐจ์ ๋ ๋๋ง ์ปจํ ์คํธ๋ฅผ ๋ํ๋ด๋ `WebGLRenderingContext๊ฐ์ฒด๋ฅผ ์์ฑbitmaprenderer
: ์บ๋ฒ์ค์ ์ปจํ ์ธ ๋ฅผ ์ฃผ์ด์งImageBitmap
(en-US)์ผ๋ก ๋์ฒดํ๊ธฐ์ํ ๊ธฐ๋ฅ๋ง์ ์ ๊ณตํ๋ImageBitmapRenderingContext
(en-US)๋ฅผ ์์ฑ
-
2d์์ ์ง์ฌ๊ฐํ , ํ ์คํธ, ์ ์ ๊ทธ๋ฆด ์ ์๊ณ , ์๋ ๋งํฌ๋ฅผ ์ฐธ๊ณ .
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D
์ฑ์ฐ๊ธฐ ๋ฐ ํ ์คํ์ผ
ctx.strokeStyle
: ๋ํ ์ฃผ์์ ์ ์ ์ฌ์ฉํ ์์ ๋๋ ์คํ์ผ. ๊ธฐ๋ณธ๊ฐ #000
์ ์คํ์ผ
ctx.lineJoin
: ๋ ์ ์ด ๋ง๋๋ ๋ชจ์๋ฆฌ ์ ํ์ ์ ์- round, bavel, miter(๊ธฐ๋ณธ๊ฐ)
ctx.lineCap
: ์ค ๋์ ์๋ฉ ์ ํ.- butt(๊ธฐ๋ณธ๊ฐ), round, square
ctx.lineWidth
: ์ ์ ๋๋น, ๊ธฐ๋ณธ๊ฐ 1.0
๊ฒฝ๋ก
๊ฐ์ฒด์ ๊ฒฝ๋ก๋ฅผ ์กฐ์ ๊ฐ๋ฅ.
beginPath()
: ํ์ ๊ฒฝ๋ก ๋ชฉ๋ก์ ๋น์ ์ ๊ฒฝ๋ก๋ฅผ ์์.moveTo()
: ์ ํ์ ๊ฒฝ๋ก์ ์์์ ์ (x, y)์ขํ๋ก ์ด๋ํจ.lineTo()
: ํ์ฌ ํ์ ๊ฒฝ๋ก์ ๋ง์ง๋ง ์ ์ ์ง์ ๋ (x, y)์ขํ์ ์ง์ ์ผ๋ก ์ฐ๊ฒฐํจ.stroke
: ํ์ฌ ํ ์คํ์ผ๋ก ํ์ฌ ํ์ ๊ฒฝ๋ก๋ฅผ ํ์ ๊ทธ์.
๐ ๊ณผ์
๐ 1. ๊ทธ๋ฆฌ๊ธฐ ํจ๊ณผ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ๊ธฐ๋ณธ ์ค์ .
const canvas = document.querySelector("#draw");
const ctx = canvas.getContext('2d');
// canvas resize
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx.strokeStyle = '#BADA55';
ctx.lineJoin = 'round';
ctx.lineCap = 'round'
ctx.lineWidth = 0;
๊ทธ๋ฆด ์บ๋ฒ์ค(#draw)๋ฅผ canvas์ ์ ์ฅํ๊ณ ctx์ canvas์ ๊ทธ๋ฆฌ๊ธฐ ๋์์ด ๋๋ context๋ฅผ ์ป์.
width์ height์๋ฅผ ์ค์ ํ๊ณ ,
์ ์ ์(strokeStyle), ์ ์ ๋๋ชจ์(lineCap), ๋๊ฐ ์ ์ด ๋ง๋๋ ์ง์ ์ ๋ชจ์(lineJoin)๊ณผ ์ ์ ๋๊ผ(lineWidth)์ง์ .
๐ 2. ๊ทธ๋ฆฌ๊ธฐ ํจ๊ณผ๋ฅผ ์ค์๊ฐ์ผ๋ก ๋ณ๊ฒฝํ๊ธฐ ์ํ ๋ณ์ ์ค์
let isDrawing = false;
let lastX = 0;
let lastY = 0;
let hue = 0;
let direction = true;
isDrawing์ ํ์ฌ ๊ทธ๋ฆฌ๊ณ ์๋์ง ์๋์ง check
lastX์ lastY๋ฅผ ์ด์ฉํด ์์์ง์ ์ขํ๋ฅผ ์ง์ .
hue๋ฅผ ํตํด ์ ์ ์์ ๋ณ๊ฒฝ.
direction์ผ๋ก ๊ตต๊ธฐ๋ฅผ ์ ํ๋ ๋ฐฉํฅ์ ์ค์ .
๐ 3. ๊ทธ๋ฆฌ๊ธฐ ํจ๊ณผ๋ฅผ ์ค์๊ฐ์ผ๋ก ๋ฐ๊พธ๋ ํจ์ ์์ฑ
// ๋ง์ฐ์ค๋ฅผ ํด๋ฆญํ ๋ ์์์ง์ ์ฌ์ค์ .
canvas.addEventListener('mousedown', (e)=>{
isDrawing = true;
[lastX, lastY] = [e.offsetX, e.offsetY];
});
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mouseup', ()=>isDrawing = false);
canvas.addEventListener('mouseout', ()=>isDrawing = false);
mouse eventํ์ธ.
๐ 4. ๊ทธ๋ฆฌ๊ธฐ ํจ๊ณผ๋ฅผ ์ค์๊ฐ์ผ๋ก ๋ณ๊ฒฝํ๊ธฐ ์ํ ํจ์ ์์ฑ.
function draw(e){
// stop the function from running when they are not moused down
// ๋ง์ฐ์ค๋ฅผ ๋๋ฅด์ง ์์ ๋ ๊ธฐ๋ฅ ์คํ ์ค์ง
if(!isDrawing) return;
console.log(e);
ctx.strokeStyle = `hsl(${hue}, 100%, 50%)`;
// ctx.lineWidth = hue;
ctx.beginPath();
// start from
ctx.moveTo(lastX, lastY);
// goto
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
// ๋ง์ง๋ง ์ง์ ์ ๋์ง์ ์ผ๋ก ์ง์ .
// ๋ค์์ ๊ทธ๋ฆด ๋ ์์์ง์ ์ด ์ด์ ์์
์ ๋์ง์ .
// lastX = e.offsetX;
// lastY = e.offsetY;
[lastX, lastY] = [e.offsetX, e.offsetY];
hue++;
// reset
if(hue >=360){
hue = 0;
}
// ctx.lineWidth++;
if(ctx.lineWidth >= 100 || ctx.lineWidth <= 1){
direction = !direction;
}
if(direction){
ctx.lineWidth++;
}else{
ctx.lineWidth--;
}
}
lastX์ lastY๋ฅผ ์ค์ ํด์ค์ ๋ฐ๋ผ ๋ณํ.
hue๊ฐ ๋ณํ.
๊ทธ ํ direction์ ๋ฐ๋ผ ๊ตต๊ธฐ์กฐ์ .
๐ 5. multiply
ctx.globalCompositeOperation = 'multiply';
์์ด ๊ฒน์น๊ฒ ๋ณด์ด๊ฒ ๋จ.
๋ ๋ง์ ์์ฑ์ด ๊ณต์ ๋ฌธ์์ ์์ผ๋ ์ฐธ๊ณ ํ์!
Author And Source
์ด ๋ฌธ์ ์ ๊ดํ์ฌ([JavaScript30] ๐ 08. FUN WITH HTML5 CANVAS), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค https://velog.io/@cjh951114/JavaScript30-08.-FUN-WITH-HTML5-CANVAS์ ์ ๊ท์: ์์์ ์ ๋ณด๊ฐ ์์์ URL์ ํฌํจ๋์ด ์์ผ๋ฉฐ ์ ์๊ถ์ ์์์ ์์ ์ ๋๋ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ ์ธ ๋ฐ๊ฒฌ์ ์ ๋ (Collection and Share based on the CC Protocol.)
์ข์ ์นํ์ด์ง ์ฆ๊ฒจ์ฐพ๊ธฐ
๊ฐ๋ฐ์ ์ฐ์ ์ฌ์ดํธ ์์ง
๊ฐ๋ฐ์๊ฐ ์์์ผ ํ ํ์ ์ฌ์ดํธ 100์ ์ถ์ฒ ์ฐ๋ฆฌ๋ ๋น์ ์ ์ํด 100๊ฐ์ ์์ฃผ ์ฌ์ฉํ๋ ๊ฐ๋ฐ์ ํ์ต ์ฌ์ดํธ๋ฅผ ์ ๋ฆฌํ์ต๋๋ค