ย ์ ๊ฐ ํ์ํด์ ์ ๋ฆฌํ๊ฒ ๋์ต๋๋ค. ์ถ์ฒ๋ Canvas ๊ณต์ ํธ๋๋ถ์
๋๋ค.
์์ธํ ์ฌํญ์ ๊ผญ ํธ๋๋ถ์ ์ฐธ๊ณ ํ์๊ธฐ๋ฅผ ๊ถ์ฅ๋๋ฆฝ๋๋ค.
<canvas>
์ ๋๋ฉ์ด์
, ๊ฒ์ ๊ทธ๋ํฝ, ๋ฐ์ดํฐ ์๊ฐํ, ์ฌ์ง ์กฐ์, ์ค์๊ฐ ๋น๋์ค ์ฒ๋ฆฌ๋ฅผ ์ํด ์ฌ์ฉ๋๋ HTML ์์์ด๋ค.
์ฃผ๋ก 2D ๊ทธ๋ํฝ์ ์ค์ ์ ๋๊ณ ์์ผ๋ฉฐ, WebGL๋ํ ์ด <canvas>๋ฅผ ์ฌ์ฉํ๋ค.
<canvas> ์ฌ์ฉ๋ฒ
๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ผ๋ก HTML ๋ฌธ์์ ์๋์ ํ๊ทธ๋ฅผ ์
๋ ฅํ์ฌ ์ฌ์ฉํ ์ ์๋ค.
canvas๋ ์ผ๋ฐ์ ์ธ ์ด๋ฏธ์ง์ฒ๋ผ ์คํ์ผ(CSS)์ ์ ์ฉ์ํฌ ์ ์๋ค.
์ฆ, margin, background ๋ฑ์ ์ฌ์ฉํ ์ ์๋ค๋ ์๋ฏธ์ด๋ค.
ํ์ง๋ง ์บ๋ฒ์ค ์์ ๊ทธ๋ฆฌ๋ ๊ฒ์๋ ์ํฅ์ ๋ฐ์ง ์๋๋ค.
๋์ฒด๋ก JavaScript์ ๊ฐ์ ์คํฌ๋ฆฝํธ๋ฅผ ์ด์ฉํ์ฌ ์บ๋ฒ์ค ์์ ์ปจํ
์ธ ๋ฅผ ๊ทธ๋ฆฐ๋ค.
<canvas> ์์ฑ(attribute)
โข
์์ฑ์ผ๋ก๋ ๊ธ๋ก๋ฒHTML ์์ฑ(id, class ๋ฑ)์ด ๋ ์ ์๋ค.
โข
width, height ์์ฑ์ ํตํด ์บ๋ฒ์ค์ ๋๋น์ ๋์ด๋ฅผ ์ค์ ํ๋ค.
โ DOM ํ๋กํผํฐ๋ฅผ ์ฌ์ฉํ์ฌ ์ค์ ํ ์๋ ์๋ค.
โ ๊ธฐ๋ณธ๊ฐ์ width=300, height=150์ด๋ค.
<canvas id="canvas">๋์ฒด ์ฝํ
์ธ ๋ ์ฌ๊ธฐ์ ์์ฑํ๋ค</canvas>
JavaScript
๋ณต์ฌ
JavaScript
์ดํ, JavaScript ํ์ผ์์ <canvas> ์ฐธ์กฐ๋ฅผ ์ป๋๋ค.
const canvas = document.querySelector("canvas");
JavaScript
๋ณต์ฌ
getContext ๋ฉ์๋๋ฅผ ํตํด์ ๋ ๋๋ง ์ปจํ
์คํธ๋ฅผ ๊ตฌํ๋ค.
const ctx = boardCanvas.getContext('2d');
JavaScript
๋ณต์ฌ
์ธ์๋ก โ2dโ๋ฅผ ์ ๋ฌํ์ง๋ง ๊ทธ์ธ์๋ webgl, webgl2 ๋ฑ์ ์ ๋ฌํ ์ ์๋ค.
์ฌ๊ธฐ๊น์ง๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ์ค๋นํด์ผํ๋ ์ฌํญ์ด๊ณ , ์ด์ JavaScript๋ฅผ ํตํด ์บ๋ฒ์ค๋ฅผ ๋ง์๊ป ๊ทธ๋ ค๋ณด์.
๊ทธ๋ฆฌ๋๋ฐ ํ์ํ ๋ฉ์๋๋ ๋ค์๊ณผ ๊ฐ๋ค.
์บ๋ฒ์ค์ ๋๋น, ๋์ด ๋ณ๊ฒฝ : width, height
์ฐธ๊ณ ๋ก JavaScript๋ก ์บ๋ฒ์ค์ ๋๋น์ ๋์ด๋ฅผ ์ค์ ํ ์ ์๋ค.
// const canvas = document.querySelector("canvas");
// const context = canvas.getContext('2d');
canvas.width = 300;
canvas.height = 300;
// ๋๋
context.canvas.width = 300;
context.canvas.height = 300;
JavaScript
๋ณต์ฌ
๋ ์ฝ๋์ ์ฐจ์ด์ ์ ์๋ค.
๋ฉ์๋์ ๋ํ ๊ธฐ๋ฅ ์ค๋ช
์ Canvas ํธ๋๋ถ์ ์ ๋์์์ผ๋ ํ์ํ ๋ ํธ๋๋ถ์ ์ฐพ์๋ณด๋ฉด ๋ ๊ฒ ๊ฐ๋ค.
ํ๋ํ๋ ์ ๋ถ ์ ๋ฆฌํ๊ธฐ์๋ ๋๋ฌด ๋ง๋ค.
๋์ ์์๋ฅผ ํ๋ ๋ง๋ค์ด์ canvas๊ฐ ์ค์ ๋ก ์ด๋ป๊ฒ ์ฐ์ด๋์ง ๋ณด๊ธฐ๋ก ํ์.
์์. ๊ฝ ๊ทธ๋ฆฌ๊ธฐ
โข
quadraticCurveTo ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ค.
โข
๋๋ถ๋ถ์ ๋ฉ์๋๋ degree๊ฐ ์๋๋ผ radian์ด๋ค.
๋๋ฌธ์ ์ฝ๊ฐ์ ํธ์์ฑ์ ์ํ์ฌ RaToDeg ํจ์๋ฅผ ๋ง๋ค์ด์ ์ฌ์ฉํ๋ค.
๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค.
์ฐ์ HTML ํ์ผ์์ <canvas> ํ๊ทธ๋ฅผ ์ฌ์ฉํด์ผํ๋ค.
<!-- HTML ํ์ผ -->
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<canvas id="game-board" width="600" height="600"></canvas>
<script src="practice.js"></script>
</body>
</html>
JavaScript
๋ณต์ฌ
๋ค์, JSํ์ผ์์ ์บ๋ฒ์ค์ ๊ทธ๋ฆผ์ ๊ทธ๋ฆผ์ ๊ทธ๋ฆด ์ฐจ๋ก์ด๋ค. ๋จผ์ ์ปจํ
์คํธ๋ฅผ ์ป์ด์จ๋ค.
/* JS ํ์ผ */
// ์ปจํ
์คํธ ์ป์ด์ค๊ธฐ
const canvas = document.querySelector("canvas");
const context = canvas.getContext('2d');
JavaScript
๋ณต์ฌ
๊ฝ์ ์ค์ฌ์ ์ขํ๋ (150, 150)์ผ๋ก ์ค์ ํ์๋ค.
// ๊ฝ์ ์ค์ฌ์ด ๋ ์ขํ๊ฐ ๋ณ์๋ก ์ ์
let width_mid = 150;
let height_mid = 150;
const rad = 100;
JavaScript
๋ณต์ฌ
save ๋ฉ์๋๋ฅผ ํตํด์ ์ด๊ธฐ์ ์ปจํ
์คํธ๋ฅผ ์ ์ฅํด๋๋๋ค.
save๋ ํ์ฌ์ ์ปจํ
์คํธ๋ฅผ ์ ์ฅํ๋ ๋ฉ์๋์ด๋ค.
๊ฐ์ฅ ์ต๊ทผ์ ์ ์ฅํด๋์ ์ปจํ
์คํธ๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ ๋๋ restore ๋ฉ์๋๋ฅผ ์ด์ฉํ๋ค.
// ์ด๊ธฐ์ ์ปจํ
์คํธ๋ฅผ ์ ์ฅํด๋๋๋ค.
context.save();
JavaScript
๋ณต์ฌ
์ธ์๋ก ์ ๋ฌ๋๋ ๊ฐ์ ๋๋ถ๋ถ ๋(degree)๊ฐ ์๋๋ผ ๋ผ๋์(radian)์ด๋ค.
์ข ๋ ์ง๊ด์ ์ผ๋ก ์ดํดํ๊ธฐ ์ํด์ radianโdegree๋ก ๋ณํํ๋ ํจ์๋ฅผ ์ ์ํ์๋ค.
function RadToDeg(angle) {
return angle * Math.PI / 180;
}
JavaScript
๋ณต์ฌ
์ด์ ๊ฝ์์ ํ๋์ฉ ๊ทธ๋ ค์ผํ๋ค.
1.
๋จผ์ beginPath ๋ฉ์๋๋ฅผ ํตํด ์๋ก์ด ๊ฒฝ๋ก๋ฅผ ๋ง๋ ๋ค.
function drawPetal(ctx, rad, i) {
ctx.beginPath(); // ์ ๊ฒฝ๋ก๋ฅผ ๋ง๋ค๊ฑฐ๋ ํ์ฌ ๊ฒฝ๋ก๋ฅผ ์ฌ์ค์ ํ๋ค.
JavaScript
๋ณต์ฌ
2.
setTransform() ๋ฉ์๋๋ฅผ ํตํด scale()๊ณผ translate()๋ฅผ ํ๋ฒ์ ์ง์ ํ๋ค.
ctx.setTransform(1, 0, 0, 1, width_mid, height_mid);
JavaScript
๋ณต์ฌ
์ฌ๊ธฐ์์ transform() ๋ฉ์๋๊ฐ ์๋ setTransform() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ด์ ๊ฐ ์๋ค.
์ผ๋จ, ์บ๋ฒ์ค์ ๊ฐ ๊ฐ์ฒด๋ ์์ฑ๋ ๋ โcurrent transformation matrix(ํ์ฌ ๋ณํ ํ๋ ฌ)โ์ด๋ผ๋ ๊ฒ์ ๊ฐ๊ฒ ๋๋ค.
โป ์์ธํ ๋ด์ฉ์ MDN ๋ฌธ์๋ฅผ ํ์ธ
transform() ๋ฉ์๋์ ํน์ง์ ์ด์ ์ ์ฌ์ฉํ transform ๋ฉ์๋(ํน์ rotate, scale, translate ๋ฉ์๋)์ ์๋์ ์ผ๋ก ์๋ํ๋ค๋ ์ ์ด๋ค.
์๋ฅผ ๋ค์ด์, ์์์ ์ด๋ฏธ scale(2, 2);๋ฅผ ์ํํ ์ํ๋ผ๋ฉด
์ด๋ transform ๋ฉ์๋๋ฅผ ์ด์ฉํด์ ์บ๋ฒ์ค์ ๋ฐฐ์จ์ 2๋ก ์ค์ ํ๋ฉด ์ด ๋ฐฐ์จ์ 4๊ฐ ๋๋ค.
context.scale(2, 2);
context.tranform(2, 0, 0, 2, 0, 0);
// ์ด ๋ฐฐ์จ์ 4๊ฐ ๋๋ค.
JavaScript
๋ณต์ฌ
ํ์ง๋ง setTransform ๋ฉ์๋๋ ์ด๋ฏธ ์บ๋ฒ์ค๊ฐ ์ด๋ค ๋ณํ์ด ์์๋ ๊ฐ์ ํ์ฌ ๋ณํ ํ๋ ฌ์ ์ฌ์ ์ํ๋ค.
context.scale(2, 2);
context.setTransform(2, 0, 0, 2, 0, 0);
// ์ด ๋ฐฐ์จ์ 2๊ฐ ๋๋ค.
JavaScript
๋ณต์ฌ
๋ฐ๋ผ์ ์ฌ๊ธฐ์์๋ setTransform ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ ์ ํ๋ค.
3.
๊ฝ์์ ํ์ ์ํค๋ฉฐ ๊ทธ๋ฆฌ๊ธฐ ์ํด์ rotate ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.
ctx.rotate(RadToDeg(30) * i); // ํ์ ์ํจ๋ค.
JavaScript
๋ณต์ฌ
2์์ setTransform ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ด์ ๋ ๋ฐ๋ก ์ด ํ์ ์ ์ข ๋ ํธํ๊ฒ ํ๊ธฐ ์ํด์์ด๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก rotate ๋ฉ์๋๋ (0, 0)์ ๊ธฐ์ค์ผ๋ก ํ์ ํ๋ค.
์ฆ, ๊ฝ์ ์ค์ฌ์ (150, 150)์ธ๋ฐ ๊ฝ์์ (0, 0)์ ๊ธฐ์ค์ผ๋ก ํ์ ์ํค๋ฉฐ ๊ทธ๋ ค์ผํ๋ค. ๊ต์ฅํ ๋ฒ๊ฑฐ๋กญ๋ค.
๋๋ฌธ์ ์์ ์ ๊ฝ์ ์ค์ฌ์ธ (150, 150)์ผ๋ก ์ด๋์์ผ์, ์๋ก์ด ์์ ์ ๊ธฐ์ค์ผ๋ก ๊ฝ์์ ํ์ ์ํค๊ธฐ ์ํด์ ์์์ setTransform์ ์ฌ์ฉํ๋ค.
4.
quadraticCurveTo ๋ฉ์๋๋ ๋ฒ ์ง์ด ๊ณก์ (Bezier Curves)๋ฅผ ๋ง๋๋ ๋ฉ์๋์ด๋ค.
๋ฒ ์ง์ด ๊ณก์ ์ ๋ง๋ค๊ณ (quadraticCurveTo ๋ฉ์๋),
ํฌ๋ช
๋(globalAlpha ์์ฑ)์ ์์(fillStyle ์์ฑ)์ ์ ํํ ํ
ํด๋น ๊ณต๊ฐ์ ์ฑ์ด๋ค. (fill ๋ฉ์๋)
ctx.moveTo(0, 0);
ctx.quadraticCurveTo(rad / 2, -(rad / 2), rad, 0);
ctx.quadraticCurveTo(rad / 2, +(rad / 2), 0, 0);
ctx.globalAlpha = "0.8";
ctx.fillStyle = "#6633CC";
ctx.fill();
ctx.restore();
JavaScript
๋ณต์ฌ
์ฐธ๊ณ ๋ก, ์๋์ ๊ฐ์ ๊ทธ๋ฆผ์ด 2์ฐจ ๋ฒ ์ง์ด ๊ณก์ ์ ํด๋นํ๋ค.
์ถ์ฒ : ์ํค๋ฐฑ๊ณผ
๋ ๊ฐ์ ๊ณก์ ์ ๊ทธ๋ ค์ฃผ๊ธฐ ์ํด์ ๋ฉ์๋๋ ๋๋ฒ ํธ์ถํ๊ณ , ์์ ์ฑ์์ฃผ์๋ค.
globalAlpha ์์ฑ์ ํฌ๋ช
๋๋ฅผ ์กฐ์ ํ ์ ์๋ค.
๋ง์ง๋ง์ restore() ๋ฉ์๋๋ฅผ ํตํด ๊ฐ์ฅ ์ต๊ทผ์ ์ ์ฅํด๋์ ์ปจํ
์คํธ๋ก ๋ณต๊ตฌํ์๋ค.
์ฐธ๊ณ ๋ก 2์ฐจ ๋ฒ ์ง์ด ๊ณก์ ์ quadraticCurveTo ๋ฉ์๋๋ก ๊ทธ๋ฆด ์ ์๊ณ
3์ฐจ ๋ฒ ์ง์ด ๊ณก์ ์ bezierCurveTo ๋ฉ์๋๋ก ๊ทธ๋ฆด ์ ์๋ค.
โป ํ๋ฉด์ ๊ทธ๋ฆผ์ ๊ทธ๋ ค์ฃผ๋ fill ๋ฉ์๋๋ฅผ ๋ง๋๊ธฐ ์ ๊น์ง๋ ๊ตฌ์ฑํด๋์ ๊ฒ๋ค(๋ฒ ์ง์ด ๊ณก์ , ์์ ๋ฑ)์ด ํ๋ฉด์ ๋ณด์ด์ง ์๋ ๊ฒ์ด ์ ์์ด๋ค.
5.
๋ง์ง๋ง์ผ๋ก ํจ์๋ฅผ ํธ์ถํด์ ๊ฝ์ 12์ฅ์ ๊ทธ๋ฆฐ๋ค.
for (let i = 1; i <= 12; i++)
drawPetal(context, rad, i);
JavaScript
๋ณต์ฌ
์ด๋ ๊ฒ canvas๋ฅผ ์ด์ฉํด์ ๊ฝ์ ๊ทธ๋ฆด ์ ์๋ค.
์ ์ฒด ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ๋ค.
์ฌ์ค ์ฝ๋๋ฅผ ์์ ํ ํ์๊ฐ ์๊ธฐ๋ ํ์ง๋ง, ์์๋ก ์ฌ์ฉํ ์ฝ๋์ด๋ฏ๋ก ๋ฆฌํฉํ ๋ง์ ํฌ๊ธฐํ๊ธฐ๋ก ํ๋ค.
const canvas = document.querySelector("canvas");
const context = canvas.getContext('2d');
context.canvas.width = 300;
context.canvas.height = 300;
let width_mid = 150;
let height_mid = 150;
const rad = 100;
context.save();
console.log(context.getTransform());
function RadToDeg(angle) {
return angle * Math.PI / 180;
}
function drawPetal(ctx, rad, i) {
ctx.beginPath();
ctx.scale(1, 1);
ctx.setTransform(1, 0, 0, 1, width_mid, height_mid);
console.log(ctx.getTransform());
ctx.rotate(RadToDeg(30) * i);
ctx.moveTo(0, 0);
ctx.quadraticCurveTo(rad / 2, -(rad / 2), rad, 0);
ctx.quadraticCurveTo(rad / 2, +(rad / 2), 0, 0);
ctx.globalAlpha = "0.8";
ctx.fillStyle = "#6633CC";
ctx.fill();
ctx.restore();
}
for (let i = 1; i <= 12; i++)
drawPetal(context, rad, i);
context.restore();
JavaScript
๋ณต์ฌ
์ด ์ธ์๋ lineTo, arc, arcTo, fillRect, fillText ๋ฑ ๊ต์ฅํ ๋ค์ํ๊ณ ์ฌ๋ฏธ์๋ ๋ฉ์๋๊ฐ ๋ง์ด ์๋ค. ๊ผญ ์ฌ์ฉํด๋ณด์.
p.s. ์ฌ๊ธฐ์์ ์ข ๋ ์์ฉํ๋ฉด, ํด๋ฆญํ๊ฑฐ๋ ๋๋๊ทธํ ๋ ์์ง์ด๊ฒ ํ๋ ๋ฑ ์ ๋๋ฉ์ด์
๋ ์ ์ฉํ ์ ์๋ค๊ณ ํ๋ค.