요약
분류 | 코드 | ||||||||||||||||||||||||||||||||||||||||||||
객체 |
ctx.beginPath(); // 그리기 시작 ctx.endPath(); // 그리기 끝 ctx = new Path2D(); // 빈 객체 생성 ctx = new Path2D(path); // 다른 Path2D 또는 SVG 객체 복사 |
||||||||||||||||||||||||||||||||||||||||||||
도형 |
ctx.fillRect(25, 25, 100, 100); // 채워진 사각형(좌표x,y, 크기x,y) ctx.strokeRect(150, 25, 100, 100); // 빈 사각형(…) ctx.clearRect(350,50,100,50); // 지우기 사각형(…) |
||||||||||||||||||||||||||||||||||||||||||||
선 |
ctx.lineTo(0, 100); // 선 그리기(좌표x, y) ctx.moveTo(0, 100); // 뗀선 그리기(좌표x, y) ctx.arc(75, 75, 50, 0, Math.PI * 2, true); // 원호 그리기(좌표x,y, 반지름, 시작각, 끝각, 시계방향=true) ctx.quadraticCurveTo(100, 50, 50, 100); // 2차곡선(제어점x, y, 끝점x, y) ctx.bezierCurveTo(100, 50, 10, 50, 50, 100); // 3차곡선(제어점1x, y, 제어점2x, y, 끝점x, y) ctx.ctx.fillStyle = = #0000; // 선 두께 ctx.lineWidth = 3; // 선 두께 ctx.strokeStyle = 'butt' | 'round' | 'square'; // 선 끝 처리 ctx.lineJoin = 'round' | 'bevel' | 'miter'; // 선 연결점 처리 ctx.miterLimit = 10; // 선 연결점 임계(허용하는 최대) 각 ctx.setLineDash([4, 2]); // 점선 그리기 [주기1, 주기2, ...] ctx.lineDashOffset= 10; // 점선 오프셋 |
||||||||||||||||||||||||||||||||||||||||||||
색상 |
ctx.fillStyle = '#0000' // 채우기 색 myColor = ctx.createLinearGradient(0, 0, 100, 100); // 그라데이션(시작x, y, 끝x, y); myColor = ctx.createRadialGradient(1,2,3,4,5,6); // 원형 그라데이션 (시작x, y, r, 끝x, y, r); myColor.addColorStop(0, '#0000'); // 그라데이션 세부 설정(0 ~ 1 사이 소수, 색); ctx.strokeStyle = myColor | '#0000'; // 외곽선 색 ctx.fillStyle = myColor | '#0000'; // 채우기 색 ctx.stroke(); // 외곽선 그리기 ctx.fill(); // 경로 채우기 [() | (경로) | (규칙) | (경로, 규칙)], 규칙 = [nonzero | evenodd] |
||||||||||||||||||||||||||||||||||||||||||||
이미지 |
<canvas id="patternImage" style="display:none;"></canvas> var patternImage = document.getElementById("patternImage"); var ctxImg = patternImage.getContext("2d"); var img = new Image();// img 테그를 가져올 수 도 있음 img.src = "https://..."; img.onload = function () { ctxImg.drawImage(img, 0, 0, newWidth, newHeight); var ptrn = ctx.createPattern(patternImage, "repeat"); &ctx.fillStyle = ptrn; ctx.drawImage(이미지, 시작점x, y); // 이미지는 html tag를 getElementById로 불러올 수도 있다. ctx.drawImage(이미지, 시작점x, y, 조정될 크기w, h); // 크기조정 ctx.drawImage(이미지, 잘라낼크기x, y, w, h, 붙여넣을크기x, y, w, h); // 이미지 자르기 |
||||||||||||||||||||||||||||||||||||||||||||
그림자 |
ctx.shadowOffsetX = 2; ctx.shadowOffsetY = 2; ctx.shadowBlur = 2; ctx.shadowColor = "#0007"; ctx.filter = "CSS 필터";
|
||||||||||||||||||||||||||||||||||||||||||||
폰트 |
ctx.font = "italic bolder 48px '궁서'"; ctx.textAlign = start; // 텍스트 정렬 : start, end, left, right, center ctx.textBaseline = top; // 글자 출력 높이 : top, hanging, middle, alphabetic, ideographic, bottom ctx.direction = ltr; // 글자 방향 : ltr(left to right), rtl, inherit(system) var text = ctx.measureText("input text"); text.width // 입력한 텍스트의 가로 길이 |
||||||||||||||||||||||||||||||||||||||||||||
저장 불러오기 |
ctx.save(); ctx.restore(); ctx.translate(x축 이동, y축 이동); // 이동 ctx.ratate(각도(라디안)); // 회전 : 원점 기준 시계방향으로 회전 ctx.scale(x확대율, y확대율); // 확대, 응용 : -1을 넣어 뒤집힌 효과도 가능 ctx.transform(a, b, c, d, e, f); // 3차원 회전 ctx.resetTransform(); = ctx.transform(1,0,0,1,0,0); ctx.clip(); // 자르기 |
||||||||||||||||||||||||||||||||||||||||||||
이벤트 |
setInterval(함수명, delay); // delay = 1/1000초, 계속 호출 setTimeout(함수명, delay); // 한번만 호출 addEventListener("이벤트명", 콜백함수); // mouseout, mouseover window.requestAnimationFrame(콜백함수); //애니메이션으로 호출할 함수 window.cancelAnimationFrame(핸들러); // 애니메이션 취소 |
다운로드
canvas = document.getElementById("canvas");
// 호출이 되는 순간의 모습을 이미지로 저장합니다.
const pngDataUri = canvas.toDataURL("image/png");
// 링크에 주소와 파일명을 저장해서 클릭되었을 때 이미지를 다운로드 합니다.
var link = document.getElementById("link");
link.href = pngDataUri;
link.download = "canvas.png";
추가
iframe안에 있는 canvas를 조작하는 방법, button을 클릭했을 때 다운로드 함수를 만드는 방법을 기술합니다.
<script>
var iframe = document.getElementById("download-iframe");
var canvas;
// iframe의 조작 시점은, 파일이 로딩 된 후여야 합니다.
iframe.onload = function () {
// iframe의 document형식으로 접근해야합니다.
canvas = iframe.contentWindow.document.getElementById("canvas");
}
// 버튼이 눌렸을 때, 동작합니다.
function download() {
// 현재의 모습을 캡쳐합니다.
const pngDataUri = canvas.toDataURL("image/png");
// 임시 엥커(anchor)를 만들어서 다운로드 후, 삭제합니다.
var link = document.createElement("a");
link.href = pngDataUri;
link.download = "canvas.png";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
</script>
MSDN에서 전하는 팁
반복객체 미리 그리기
반복 작업이 되는 그림을 미리 그린 후 주 캔버스에 넣으면 랜더링을 줄일 수 있습니다.
myCanvas.offscreenCanvas = document.createElement('canvas');
myCanvas.offscreenCanvas.width = myCanvas.width;
myCanvas.offscreenCanvas.height = myCanvas.height;
myCanvas.getContext('2d').drawImage(myCanvas.offScreenCanvas, 0, 0);
부동소수점 피하기
부동소수점은 부가적인 픽셀렌더링이 발생됩니다. Math.floor()를 사용하여, 정수화합니다.
drawImage에서 크기조정 피하기
오프스크린(offscreen) 캔버스에서 캐시하면 유리합니다. 만약 큰 배경이미지는 CSS의 background속성을 이용하면 매 틱마다 랜더링하지 않아도 됩니다. 또한 CSS 변환은 GPU를 사용하기 때문에 더 빠릅니다.
여러개의 캔버스를 사용하기
아래 예시는 게임UI를 상정하였습니다. 움직임이 적은 배경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>
투명도 사용을 가급적 피하기
투명 배경을 사용하지 않을 때 아래 옵션을 사용하여 최적화 할 수 있습니다.
// 투명 배경을 피하는 방법
var ctx = canvas.getContext('2d', { alpha: false });
기타 팁들
- 배치 캔버스를 함께 호출합니다. 예를 들어 여러 개의 개별 선 대신 다각형 선을 그립니다.
- 불필요한 캔버스 상태 변경을 피하십시오.
- 화면의 차이만 렌더링하고 완전히 새로운 상태로 렌더링하지 마십시오.
- 가능하면 shadowBlur 속성을 사용하지 마십시오.
- 가능하면 텍스트 렌더링을 피하십시오.
- 캔버스를 지우는 여러 가지 방법을 시도해보십시오 (clearRect() vs. fillRect() vs. 캔버스 크기 조정).
- 애니메이션에서는 window.setInterval() 대신 window.requestAnimationFrame()을 사용하십시오.
- 무거운 물리 연산 라이브러리를 주의하십시오.