ìºë²ì¤ ìµì í
<canvas> ì리먼í¸ë ì¹ìì 2D ê·¸ëí½ì ë ëë§íë ë° ê°ì¥ ë리 ì¬ì©ëë ë구 ì¤ íëì
ëë¤. ê·¸ë¬ë ì¹ ì¬ì´í¸ì ì±ì´ Canvas API를 ìµëíì¼ë¡ ë°ë©´ ì±ë¥ì´ ì íë기 ììí©ëë¤. ê·¸ë¬ë ì¹ ì¬ì´í¸ ë° ì±ì´ Canvas API를 íê³ì¹ê¹ì§ ì¬ì©íë©´ ì±ë¥ì´ ì íë기 ììí©ëë¤. ì´ ê¸ììë ê·¸ëí½ì´ ì ëìíëë¡ ë³´ì¥í기 ìí´ ìºë²ì¤ ì리먼í¸ì ì¬ì©ì ìµì íí기ìí ì ì ì¬íì ì ê³µí©ëë¤.
ì±ë¥ í
ë¤ìì ìºë²ì¤ ì±ë¥ì ê°ì í기 ìí í 모ìì ëë¤.
ìºë²ì¤ì íìëì§ ìë ë¹ì·í ìì í¹ì ë°ë³µ ê°ì²´ë¥¼ 미리 ê·¸ë ¤ë¼
ë§ì½ ë¹ì ì´ ìºë²ì¤ì ì ëë©ì´ì íë ìì 그리면ì ë°ë³µì ì¸ ìì ì´ ë°ê²¬ëë¤ë©´, ëì ë³´ì´ì§ ìë ì¨ê²¨ì§ ìºë²ì¤ ìì를 ìë¡ ë§ë¤ê³ ê·¸ ìºë²ì¤ì 미리 ê·¸ë ¤ ë£ë ë°©ë²ì ê³ ë ¤íì¸ì. ê·¸ë ê² íë©´ íìí ìê°ì ì¨ê¸´ ìºë²ì¤ì ê·¸ë ¤ì§ ì´ë¯¸ì§ë¥¼ ë¤ì 주 ìºë²ì¤ ì´ë¯¸ì§ì ê·¸ë ¤ë£ì´, ë¶íìí ë ëë§ ë°ë³µ ìì ì ì¤ì¬ ì±ë¥ í¥ìì ê¾í ì ììµëë¤.
myCanvas.offscreenCanvas = document.createElement("canvas");
myCanvas.offscreenCanvas.width = myCanvas.width;
myCanvas.offscreenCanvas.height = myCanvas.height;
myCanvas.getContext("2d").drawImage(myCanvas.offScreenCanvas, 0, 0);
ë¶ë ììì ì¢í를 í¼íê³ ëì ì ì를 ì¬ì©íë¼
ì ìê°ë¤ ìì´ ìºë²ì¤ ìì ê°ì²´ë¥¼ ë ëë§í ë ë¶ê°ì ì¸ í½ì ë ëë§ì´ ë°ìí©ëë¤.
ctx.drawImage(myImage, 0.3, 0.5);
ì´ë ê²íë©´ ì¤í° ì¨ë¦¬ì´ì±(anti-aliasing) í¨ê³¼ë¥¼ ë§ë¤ê¸° ìí´ ë¸ë¼ì°ì ìì ì¶ê° ì°ì°ì ìíí´ì¼í©ëë¤. ìì ìì ì´ë¥¼ ë°©ì§íë ¤ë©´ Math.floor()를 ì¬ì©íì¬ drawImage() í¸ì¶ì ì¬ì©ë 모ë ì¢í를 ë°ì¬ë¦¼í´ì¼í©ëë¤.
drawImageìì ì´ë¯¸ì§ í¬ê¸°ë¥¼ ì¡°ì íì§ ë§ë¼
drawImage()ìì ì¦ì í¬ê¸°ë¥¼ ì¡°ì íì§ ë§ê³ ë¤ìí ì´ë¯¸ì§ í¬ê¸°ë¥¼ ì¤íì¤í¬ë¦°(offscreen) ìºë²ì¤ì ìºìíììì¤.
ë³µì¡í ì¥ë©´ì ì¬ë¬ ê°ì ë ì´ì´ ìºë²ì¤ë¥¼ ì¬ì©íë¼
ì´í리ì¼ì´ì
ìì ì¼ë¶ ê°ì²´ë ì주 ì´ëíê±°ë ë³ê²½í´ì¼íì§ë§ ë¤ë¥¸ ê°ì²´ë ìëì ì¼ë¡ ê³ ì ìì¹ì ë¨ìì¼ í©ëë¤. ì´ë° ìí©ìì ëì ê°ë¥í ìµì íë ì¬ë¬ <canvas> ì리먼í¸ë¥¼ ì¬ì©íì¬ í목ì ê²¹ì³ì ë§ëë ê²ì
ëë¤.
ì를 ë¤ì´ ìë¨ì UI, ì¤ê°ì ê²ì íë ì´ ì¡ì
, íë¨ì ì ì ë°°ê²½ì´ìë ê²ìì´ ìë¤ê³ ê°ì í´ ë³´ê² ìµëë¤. ì´ ê²½ì° ê²ìì ì¸ ê°ì <canvas> ë ì´ì´ë¡ ëë ì ììµëë¤. UIë ì¬ì©ì ì
ë ¥ììë§ ë³ê²½ëë©° ê²ì íë ì´ ë ì´ì´ë 모ë ì íë ìë§ë¤ ë³ê²½ëë©° ë°°ê²½ì ì¼ë°ì ì¼ë¡ ë³ê²½ëì§ ììµëë¤.
<div id="stage">
<canvas id="ui-layer" width="480" height="320"></canvas>
<canvas id="game-layer" width="480" height="320"></canvas>
<canvas id="background-layer" width="480" height="320"></canvas>
</div>
<style>
#stage {
width: 480px;
height: 320px;
position: relative;
border: 2px solid black;
}
canvas {
position: absolute;
}
#ui-layer {
z-index: 3;
}
#game-layer {
z-index: 2;
}
#background-layer {
z-index: 1;
}
</style>
í° ë°°ê²½ ì´ë¯¸ì§ë ì¼ë° CSS를 ì¬ì©íë¼
ì ì ë°°ê²½ ì´ë¯¸ì§ê°ìë ê²½ì° CSS background ìì±ì ì¬ì©íì¬ ì¼ë° <div> ììì 그릴 ì ìì¼ë©° ìºë²ì¤ ìëì ë°°ì¹ í ì ììµëë¤. ì´ë ê²íë©´ 모ë í± ë§ë¤ ë°°ê²½ì ìºë²ì¤ì ë ëë§ í íìê° ìì´ì§ëë¤.
CSS ë³í(transform)ì ì¬ì©íì¬ ìºë²ì¤ í¬ê¸° ì¡°ì íë¼
CSS ë³í(transform)ì GPU를 ì¬ì©í기 ë문ì ë ë¹ ë¦ ëë¤. ê°ì¥ ì¢ì ê²½ì°ë ìºë²ì¤ë¥¼ ì¤ì¼ì¼ë§íì§ ìê±°ë, í° ìºë²ì¤ë¥¼ ì¶ìíê¸°ë³´ë¤ ìì ìºë²ì¤ë¥¼ íëíë ê²ì ëë¤.
var scaleX = window.innerWidth / canvas.width;
var scaleY = window.innerHeight / canvas.height;
var scaleToFit = Math.min(scaleX, scaleY);
var scaleToCover = Math.max(scaleX, scaleY);
stage.style.transformOrigin = "0 0"; //scale from top left
stage.style.transform = "scale(" + scaleToFit + ")";
í¬ëª ë를 ì¬ì©íì§ ë§ë¼
ìì© íë¡ê·¸ë¨ì´ ìºë²ì¤ë¥¼ ì¬ì©íê³ í¬ëª
ë°°ê²½ì íìë¡íì§ ìë ê²½ì° HTMLCanvasElement.getContext()를 ì¬ì©íì¬ ëë¡ì 컨í
ì¤í¸ë¥¼ ë§ë¤ ë alpha ìµì
ì falseë¡ ì¤ì í©ëë¤. ì´ ì ë³´ë ë ëë§ì ìµì íí기 ìí´ ë¸ë¼ì°ì ìì ë´ë¶ì ì¼ë¡ ì¬ì©í ì ììµëë¤.
var ctx = canvas.getContext("2d", { alpha: false });
ì¶ê° íë¤
- ë°°ì¹ ìºë²ì¤ë¥¼ í¨ê» í¸ì¶í©ëë¤. ì를 ë¤ì´ ì¬ë¬ ê°ì ê°ë³ ì ëì ë¤ê°í ì ì 그립ëë¤.
- ë¶íìí ìºë²ì¤ ìí ë³ê²½ì í¼íììì¤.
- íë©´ì ì°¨ì´ë§ ë ëë§íê³ ìì í ìë¡ì´ ìíë¡ ë ëë§íì§ ë§ììì¤.
- ê°ë¥íë©´
shadowBlurìì±ì ì¬ì©íì§ ë§ììì¤. - ê°ë¥íë©´ í ì¤í¸ ë ëë§ì í¼íììì¤.
- ìºë²ì¤ë¥¼ ì§ì°ë ì¬ë¬ ê°ì§ ë°©ë²ì ìëí´ë³´ììì¤ (
clearRect()vs.fillRect()vs. ìºë²ì¤ í¬ê¸° ì¡°ì ). - ì ëë©ì´ì
ììë
window.setInterval()ëìwindow.requestAnimationFrame()ì ì¬ì©íììì¤. - ë¬´ê±°ì´ ë¬¼ë¦¬ ì°ì° ë¼ì´ë¸ë¬ë¦¬ë¥¼ 주ìíììì¤.