기본 ì ëë©ì´ì
<canvas> ììë JavaScriptë¡ ì ì´íë ê²ì´ë¯ë¡, ì ëë©ì´ì
ë ì½ê² ë§ë¤ ì ììµëë¤. ë³µì¡í ì ëë©ì´ì
ì ë§ëë ê²ì ì¶ê° ìì
ì´ ë íìíê³ , ìì¼ë¡ ê·¸ì ëí íì´ì§ë ë¨¸ì§ ìì ì¶ê°ë기를 기ëí©ëë¤.
ëíì íë² ë§ë¤ì´ ëì¼ë©´ ê·¸ ëª¨ìµ ê·¸ëë¡ ìë¤ë ê²ì´ ì ëë©ì´ì ì ë§ë¤ ëì ê°ì¥ í° ì ì½ì¼ ê²ì ëë¤. ê·¸ ëíì ìì§ì´ê³ ì íë©´ ê·¸ ëíë¿ë§ì´ ìëë¼ ê·¸ ëíì´ ê·¸ë ¤ì§ê¸° ì ì ê·¸ë ¤ì§ ëª¨ë ê²ì ë¤ì ê·¸ë ¤ì¼ í©ëë¤. ë³µì¡í ì¥ë©´ì ë¤ì 그리ë ê²ì ìê°ë ë§ì´ 걸리며, ì½ë를 ì¤ííë ì»´í¨í°ì ë¥ë ¥ì ë°ë¼ ë¬ë¼ì§ëë¤.
기본 ì ëë©ì´ì ë¨ê³
í ì¥ë©´ì ê·¸ë¦¬ë ¤ë©´ ìëì ê°ì ë¨ê³ë¥¼ ë°ìµëë¤.
- ìºë²ì¤ë¥¼ ë¹ìëë¤.
ê·¸ë¦¬ë ¤ë ëíì´ (ë°°ê²½ ì´ë¯¸ì§ë¥¼ ë§ë¤ ëì²ë¼) ìºë²ì¤ë¥¼ ê°ë ì±ì°ë ê²ì´ ìëë¼ë©´, ì´ì ì ê·¸ë ¤ì§ ëª¨ë ëíì ì§ì¸ íìê° ììµëë¤. ê°ì¥ ì¬ì´ ë°©ë²ì
clearRect()ë©ìë를 ì¬ì©íë ê²ì ëë¤. - ìºë²ì¤ ìí를 ì ì¥í©ëë¤. ìºë²ì¤ ìíì ìí¥ì 주ë (ì¤íì¼ ë³ê²½, 모ì ë³í ë±ì) ì¤ì ê°ì ë°ê¾¸ë ¤ê³ íê³ , ë°ë ê°ì ê° ì¥ë©´ë§ë¤ ì¬ì©íë ¤ê³ íë¤ë©´, ìë ìí를 ì ì¥í íìê° ììµëë¤.
- ì ëë©ì´ì í ëíì 그립ëë¤. ì¤ì ì¥ë©´ì 그리ë ë¨ê³ì ëë¤.
- ìºë²ì¤ ìí를 ë³µìí©ëë¤. ìë¡ì´ ì¥ë©´ì 그리기 ì ì ì ì¥ë ìí를 ë³µìí©ëë¤.
ì ëë©ì´ì ì ì´í기
ìºë²ì¤ ë©ìë를 ì¬ì©íê±°ë ì¬ì©ì í¨ì를 ì¬ì©íì¬ ìºë²ì¤ì ëíë¤ì 그립ëë¤. ë³´íµì ê²½ì°ììë, ì½ë ì¤íì´ ìë£ëë©´ ìºë²ì¤ì ëíëë ê²°ê³¼ë§ì ë³´ê² ë©ëë¤. ì를 ë¤ì´, for ë°ë³µë¬¸ ììì ì ëë©ì´ì
ì ì¤ííë ê²ì ë¶ê°ë¥í©ëë¤.
ê·¸ëì ì í´ì§ ìê°ë§ë¤ 그리기 í¨ì를 ì¤ííë ë°©ë²ì´ íìí ê²ì ëë¤. ìëì ê°ì´ ì ëë©ì´ì ì ì ì´íë ë ê°ì§ ë°©ë²ì´ ììµëë¤.
ìì ë ë³ê²½
ì í´ì§ ìê°ë§ë¤ í¹ì í¨ì를 ë¶ë¥¼ ë ì¬ì©í ì ìë window.setInterval()ê³¼ window.setTimeout() í¨ìê° ììµëë¤.
ì°¸ê³ :
ììë ê²: íì¬ë ì ëë©ì´ì
ì ë§ëë ë°©ë²ì¼ë¡ window.requestAnimationFrame() ë©ìë를 ì¶ì²í©ëë¤. ì´ì ëí íí 리ì¼ì ê³§ ì
ë°ì´í¸í ê²ì
ëë¤.
setInterval(function, delay)-
delayë°ë¦¬ì¸ì»¨ë(1,000ë¶ì 1ì´)ë§ë¤functioní¨ì ë°ë³µ ì¤íì ììí©ëë¤. setTimeout(function, delay)-
delayë°ë¦¬ì¸ì»¨ë(1,000ë¶ì 1ì´) 경과í,functioní¨ì를 ì¤íí©ëë¤.
ì¬ì©ìì ì ì´ë¥¼ íìë¡ íì§ ìë ë°ë³µ ì¤íìë setInterval() í¨ìê° ìë§ì ê²ì
ëë¤.
ì¬ì©ì ìí¸ ìì© ë³ê²½
ì ëë©ì´ì
ì ì ì´íë ëë²ì§¸ ë°©ë²ì ì¬ì©ì ì
ë ¥ì
ëë¤. ê²ìì ë§ë¤ë ¤ê³ íë¤ë©´, ì ëë©ì´ì
ì ì ì´í기 ìí´ í¤ë³´ëë ë§ì°ì¤ ì´ë²¤í¸ë¥¼ ì¬ì©í ì ìì ê²ì
ëë¤. EventListener를 ì¤ì íì¬, ì¬ì©ìì ìí¸ ìì©íì¬ ì ëë©ì´ì
í¨ì를 ì¤íí©ëë¤.
ì¬ì©ì ìí¸ ìì©ì´ íìíë¤ë©´, ì°ë¦¬ê° ë§ë ì ëë©ì´ì ì© íë ìì(framework)ì ìµì ê¸°ë¥ ë²ì ëë ìµë ê¸°ë¥ ë²ì ì ì¬ì©í ì ìì ê²ì ëë¤.
var myAnimation = new MiniDaemon(null, animateShape, 500, Infinity);
ëë
var myAnimation = new Daemon(null, animateShape, 500, Infinity);
ìë ìì ììë, ì ëë©ì´ì
ì ì ì´í기 ìí´ window.setInterval()ì ì¬ì©í ê²ì
ëë¤. íì´ì§ ì ì¼ ìë쪽ì window.setTimeout()ì ì¬ì©í ìì ë§í¬ë ììµëë¤.
íìê³ ì ëë©ì´ì
ì´ ìì ììë ë¬ì´ ì§êµ¬ë¥¼ ëê³ ì§êµ¬ê° íìì ëë ì ëë©ì´ì ì ë§ëëë¤.
var sun = new Image();
var moon = new Image();
var earth = new Image();
function init() {
sun.src = "canvas_sun.png";
moon.src = "canvas_moon.png";
earth.src = "canvas_earth.png";
setInterval(draw, 100);
}
function draw() {
var ctx = document.getElementById("canvas").getContext("2d");
ctx.globalCompositeOperation = "destination-over";
ctx.clearRect(0, 0, 300, 300); // ìºë²ì¤ë¥¼ ë¹ì´ë¤
ctx.fillStyle = "rgba(0,0,0,0.4)";
ctx.strokeStyle = "rgba(0,153,255,0.4)";
ctx.save();
ctx.translate(150, 150);
// ì§êµ¬
var time = new Date();
ctx.rotate(
((2 * Math.PI) / 60) * time.getSeconds() +
((2 * Math.PI) / 60000) * time.getMilliseconds(),
);
ctx.translate(105, 0);
ctx.fillRect(0, -12, 50, 24); // Shadow
ctx.drawImage(earth, -12, -12);
// ë¬
ctx.save();
ctx.rotate(
((2 * Math.PI) / 6) * time.getSeconds() +
((2 * Math.PI) / 6000) * time.getMilliseconds(),
);
ctx.translate(0, 28.5);
ctx.drawImage(moon, -3.5, -3.5);
ctx.restore();
ctx.restore();
ctx.beginPath();
ctx.arc(150, 150, 105, 0, Math.PI * 2, false); // ì§êµ¬ 궤ë
ctx.stroke();
ctx.drawImage(sun, 0, 0, 300, 300);
}
ìê³ ì ëë©ì´ì
ì´ ìì ììë, íì¬ ìê°ì ë³´ì¬ì£¼ë ìì§ì´ë ìê³ë¥¼ ë§ëëë¤.
function init() {
clock();
setInterval(clock, 1000);
}
function clock() {
var now = new Date();
var ctx = document.getElementById("canvas").getContext("2d");
ctx.save();
ctx.clearRect(0, 0, 150, 150);
ctx.translate(75, 75);
ctx.scale(0.4, 0.4);
ctx.rotate(-Math.PI / 2);
ctx.strokeStyle = "black";
ctx.fillStyle = "white";
ctx.lineWidth = 8;
ctx.lineCap = "round";
// ìê³í - ì
ctx.save();
for (var i = 0; i < 12; i++) {
ctx.beginPath();
ctx.rotate(Math.PI / 6);
ctx.moveTo(100, 0);
ctx.lineTo(120, 0);
ctx.stroke();
}
ctx.restore();
// ìê³í - ë¶
ctx.save();
ctx.lineWidth = 5;
for (i = 0; i < 60; i++) {
if (i % 5 != 0) {
ctx.beginPath();
ctx.moveTo(117, 0);
ctx.lineTo(120, 0);
ctx.stroke();
}
ctx.rotate(Math.PI / 30);
}
ctx.restore();
var sec = now.getSeconds();
var min = now.getMinutes();
var hr = now.getHours();
hr = hr >= 12 ? hr - 12 : hr;
ctx.fillStyle = "black";
// ìê° íì - ì
ctx.save();
ctx.rotate(
hr * (Math.PI / 6) + (Math.PI / 360) * min + (Math.PI / 21600) * sec,
);
ctx.lineWidth = 14;
ctx.beginPath();
ctx.moveTo(-20, 0);
ctx.lineTo(80, 0);
ctx.stroke();
ctx.restore();
// ìê° íì - ë¶
ctx.save();
ctx.rotate((Math.PI / 30) * min + (Math.PI / 1800) * sec);
ctx.lineWidth = 10;
ctx.beginPath();
ctx.moveTo(-28, 0);
ctx.lineTo(112, 0);
ctx.stroke();
ctx.restore();
// ìê° íì - ì´
ctx.save();
ctx.rotate((sec * Math.PI) / 30);
ctx.strokeStyle = "#D40000";
ctx.fillStyle = "#D40000";
ctx.lineWidth = 6;
ctx.beginPath();
ctx.moveTo(-30, 0);
ctx.lineTo(83, 0);
ctx.stroke();
ctx.beginPath();
ctx.arc(0, 0, 10, 0, Math.PI * 2, true);
ctx.fill();
ctx.beginPath();
ctx.arc(95, 0, 10, 0, Math.PI * 2, true);
ctx.stroke();
ctx.fillStyle = "rgba(0,0,0,0)";
ctx.arc(0, 0, 3, 0, Math.PI * 2, true);
ctx.fill();
ctx.restore();
ctx.beginPath();
ctx.lineWidth = 14;
ctx.strokeStyle = "#325FA2";
ctx.arc(0, 0, 142, 0, Math.PI * 2, true);
ctx.stroke();
ctx.restore();
}
ìì§ì´ë íë ¸ë¼ë§ ì¬ì§
ì´ ìì ììë, ìì§ì´ë íë ¸ë¼ë§ ì¬ì§ì ë§ëëë¤. ì¬ì©í 그림ì ìí¤í¼ëì´(Wikipedia)ìì 구í ìì¸ë¯¸í° êµë¦½ê³µìì ëë¤. ìºë²ì¤ë³´ë¤ í° ê·¸ë¦¼ì ì¬ì©í ìë ììµëë¤.
var img = new Image();
// ë³ì
// ì¤í¬ë¡¤ë ì´ë¯¸ì§, ë°©í¥, ìë를 ë°ê¾¸ë ¤ë©´ ë³ìê°ì ë°ê¾¼ë¤.
img.src = "capitan_meadows,_yosemite_national_park.jpg";
var CanvasXSize = 800;
var CanvasYSize = 200;
var speed = 30; // ê°ì´ ìì ìë¡ ë¹¨ë¼ì§ë¤
var scale = 1.05;
var y = -4.5; // ìì§ ìµì
// 주ì íë¡ê·¸ë¨
var dx = 0.75;
var imgW;
var imgH;
var x = 0;
var clearX;
var clearY;
var ctx;
img.onload = function () {
imgW = img.width * scale;
imgH = img.height * scale;
if (imgW > CanvasXSize) {
x = CanvasXSize - imgW;
} // ìºë²ì¤ë³´ë¤ í° ì´ë¯¸ì§
if (imgW > CanvasXSize) {
clearX = imgW;
} // ìºë²ì¤ë³´ë¤ í° ì´ë¯¸ì§
else {
clearX = CanvasXSize;
}
if (imgH > CanvasYSize) {
clearY = imgH;
} // ìºë²ì¤ë³´ë¤ í° ì´ë¯¸ì§
else {
clearY = CanvasYSize;
}
// ìºë²ì¤ ìì ì»ê¸°
ctx = document.getElementById("canvas").getContext("2d");
// ìë¡ ê·¸ë¦¬ê¸° ìë ì¤ì
return setInterval(draw, speed);
};
function draw() {
// ìºë²ì¤ë¥¼ ë¹ì´ë¤
ctx.clearRect(0, 0, clearX, clearY);
// ì´ë¯¸ì§ê° ìºë²ì¤ë³´ë¤ ìê±°ë ê°ë¤ë©´ (If image is <= Canvas Size)
if (imgW <= CanvasXSize) {
// ì¬ì¤ì , ì²ìë¶í° ìì
if (x > CanvasXSize) {
x = 0;
}
// ì¶ê° ì´ë¯¸ì§ 그리기
if (x > CanvasXSize - imgW) {
ctx.drawImage(img, x - CanvasXSize + 1, y, imgW, imgH);
}
}
// ì´ë¯¸ì§ê° ìºë²ì¤ë³´ë¤ í¬ë¤ë©´ (If image is > Canvas Size)
else {
// ì¬ì¤ì , ì²ìë¶í° ìì
if (x > CanvasXSize) {
x = CanvasXSize - imgW;
}
// ì¶ê° ì´ë¯¸ì§ 그리기
if (x > CanvasXSize - imgW) {
ctx.drawImage(img, x - imgW + 1, y, imgW, imgH);
}
}
// ì´ë¯¸ì§ 그리기
ctx.drawImage(img, x, y, imgW, imgH);
// ìì§ì ì ë
x += dx;
}
ìì ì ì¬ì©ë <canvas>ì í¬ê¸°ë ìëì ê°ë¤. ìºë²ì¤ì ëë¹ê° ë³ì CanvasXSizeê°ê³¼ ê°ê³ , ìºë²ì¤ì ëì´ë ë³ì CanvasYSizeê°ê³¼ ê°ë¤ë ê²ì 주목íë¼.
<canvas id="canvas" width="800" height="200"></canvas>
Live sample
ë ë¤ë¥¸ ìì ë¤
- Gartic
-
ë¤ì¤ ì¬ì©ì ì§ì 그리기 ëì´.
- Canvascape
-
3D ì´ëë²¤ì² ê²ì (1ì¸ì¹ ìí ).
- A basic ray-caster
-
í¤ë³´ë를 ì¬ì©í ì ëë©ì´ì ì ì´ ë°©ë²ì ëí ì¢ì ìì .
- canvas adventure
-
í¤ë³´ë ì ì´ë¥¼ ì¬ì©íë ëë¤ë¥¸ ì¢ì ìì .
- An interactive Blob
-
ë¬¼ë°©ì¸ ê°ê³ ë기.
- Flying through a starfield
-
ë³, ëê·¸ë¼ë¯¸, ë¤ëª¨ê° ë ë¤ëë ì°ì£¼ë¥¼ ëë²¼ë¼.
- iGrapher
-
주ì ìì¥ ìë£ ì°¨í¸ ìì .