요약

canvas 문법 요약
분류 코드
객체 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 필터";// 중복 적용 가능
효과 함수 인자 예시
흐리게 blur (번짐길이) blur(2px)
밝기 brightness (밝기율%) brightness(40%)
대조 contrast (대조율%) contrast(200%)
그림자 drop-hadow (그림자거리x, y, 번짐크기, 색) drop-shadow(5px 5px 5px #444)
회색비 grayscale (회색조%) grayscale(50%)
색 회전 hue-rotate (회전각deg) hue-rotate(90deg)
반전 invert (반전율%) invert(100%)
투명도 opacity (투명률%) opacity(25%)
채도 saturate (채도%) saturate(30%)
갈색조 sepia (반영율%) sepia(60%)
폰트 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 });

기타 팁들