이 페이지는 mdn 튜토리얼 을 참고했습니다. 해당 사이트의 예제는 훌륭하지만, 일부 코드들이 동작하지 않는 버그가 있습니다. 버그 수정 및 예제 추가를 하였습니다. 모든 실습파일은 다운로드 후에 실행, 분석할 수 있습니다.
강의노트
아래 github에 업로드된 예제코드를 다운받아 실습 할 수 있습니다(E_Canvas 참조).
https://github.com/iseohyun/html-tutorial.git
준비사항
이어지는 예제 코드는 아래의 기본 코드에서 TODO부분을 채우면 됩니다. (브라우저 버전별 지원 세부사항: https://developer.mozilla.org/...브라우저 지원)
<script>
function draw() {
var ctx = document.getElementById('canvas1').getContext('2d');
<!-- TODO: intert 'Canvas API' -->
}
</script>
<body onload="draw()">
<canvas id="canvas1" width="200" , height="200"></canvas>
</body>
빈 캔버스canvas를 생성하고, 캔버스 위에 그림을 그립니다. 따라서 빈 캔버스가 완전히 로딩되고, script가 수행되어야 합니다. onload함수는 문서가 완전히 로딩이 된 후에 draw함수가 수행되도록 설계되어 있습니다. 위와 같이 호출된다면, 로딩 순서를 고민할 필요가 없습니다.
좌표계
좌표계는 캔버스의 가장 좌상단이 (0,0)이 되며, x축은 오른쪽으로 증가, y축은 하단으로 증가합니다.
도형 그리기
분류 | 도형 | 문법 |
---|---|---|
도형 | 그리기 시작 | beginPath() |
선으로 그리기 | stroke() | |
채우기 | fill() | |
이동 | moveTo(좌표x, y) | |
선 | lineTo(좌표x, y) | |
원호 | arc(중심x, y, 반지름, 시작각, 끝각, 시계방향=true) | |
베지어곡선(2차) | quadraticCurveTo(제어점x, y, 끝점x, y) | |
베지어곡선(3차) | bezierCurveTo(제어점1x, y, 제어점2x, y, 끝점x, y) | |
채워진 사각형 | fillRect(시작x, y, 크기x, y); | |
빈 사각형 | StrokeRect(시작x, y, 크기x, y); | |
특성 | 선 색 | ctx.strokeStyle = 색; |
칠하기 색 | ctx.fillStyle = 색; | |
선 굵기 | ctx.lineWidth = 숫자; | |
끝선 처리 규칙 | ctx.strokeStyle = 'butt' | 'round' | 'square'; | |
선 이음부 처리 규칙 | ctx.lineJoin = 'round' | 'bevel' | 'miter' | |
삐져나옴(bevel)처리 규칙 | ctx.miterLimit = 임계각 | |
점선 규칙 | ctx.setLineDash([주기1, 주기2 ...]); | |
점선 밀기 | ctx.lineDashOffset = 오프셋 | |
그리기 도구 |
도구 생성 도구 복사 도구 생성(경로) |
new Path2D(); new Path2D(path); new Path2D(d); |
직선
A_Start > a_line.htmllineTo(좌표x, y); // 선을 그립니다.
moveTo(좌표x, y); // 선을 그리지 않고 이동합니다.
사각형
A_Start > b_rect.htmlfillRect(시작x, y, 크기x, y); // 채워진 사각형
StrokeRect(시작x, y, 크기x, y); // 빈 사각형
ctx.fillRect(25, 25, 100, 100); // 채워진 사각형을 그립니다.
ctx.strokeRect(150, 25, 100, 100); // 빈 사각형을 그립니다.
ctx.clearRect(350,50,100,50); // 이미 그려진 것들을 지워버립니다.(사각투명)
원
원의 시작점이 3시 방향인 것에 주의합니다. 원호의 길이는 라디안radian값을 사용합니다.
arc(중심x, y, 반지름, 시작각, 끝각, 시계방향=true)
ctx.beginPath();
ctx.arc(75, 75, 50, 0, Math.PI * 2, true); // 바깥쪽 원
ctx.moveTo(110, 75);
ctx.arc(75, 75, 35, 0, Math.PI, false); // 입(시계 방향)
ctx.moveTo(65, 65);
ctx.arc(60, 65, 5, 0, Math.PI * 2, true); // 왼쪽 눈
//ctx.moveTo(95, 65); // 붓 떼기 주석처리
ctx.arc(90, 65, 5, 0, Math.PI * 2, true); // 오른 쪽 눈
ctx.stroke();
※ 위 예제코드 구현파일입니다.A_Start > c_arcs.html
곡선
곡선은 아래와 같이 시작-끝 외에 1개(2차함수) 또는 2개(베지어곡선, 3차함수)의 제어점을 갖습니다.
quadraticCurveTo(제어점x, y, 끝점x, y)
bezierCurveTo(제어점1x, y, 제어점2x, y, 끝점x, y)
※ 2차곡선의 드로잉 방식에 대한 설명을 위해 작성한 예제입니다.
2차 곡선
A_Start > d_speechBubble.html3차 곡선
선

선분이 뿌옇게 보이는 이유는 0.5 단위로 그려지기 때문입니다. 따라서 정확하게 그리고 싶다면 위와 같이 시작점을 .5로 지정해야 합니다. 단, 소수점 랜더링은 CPU에 부하를 주는 방식이기 때문에 추천하지는 않습니다.
lineWidth
ctx.lineWidth = 숫자;
// .5로 그린 선분 : 확실히 선명하게 그려진다.
ctx.moveTo(5.5, 5);
ctx.lineTo(5.5, 140);
ctx.stroke();
// 대충 굵기만 다르게 그린 선분
for (var i = 0; i < 10; i++){
ctx.lineWidth = 1 + i;
ctx.beginPath();
ctx.moveTo(5 + i * 14, 5);
ctx.lineTo(5 + i * 14, 140);
ctx.stroke();
}
A_Start > e_lineWidth.html
lineCap
ctx.strokeStyle = 'butt' | 'round' | 'square';
var lineCap = ['butt','round','square'];
// 안내선을 그린다
ctx.strokeStyle = '#09f';
ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(140, 10);
ctx.moveTo(10, 140);
ctx.lineTo(140, 140);
ctx.stroke();
// 선을 그린다
ctx.strokeStyle = 'black';
for (var i=0;i<lineCap.length;i++){
ctx.lineWidth = 15;
ctx.lineCap = lineCap[i];
ctx.beginPath();
ctx.moveTo(25 + i * 50, 10);
ctx.lineTo(25 + i * 50,140);
ctx.stroke();
}
A_Start > e2_lineCap.html
lineJoin
ctx.lineJoin = 'round' | 'bevel' | 'miter'
ctx = document.getElementById('lineJoin').getContext('2d');
var lineJoin = ['round', 'bevel', 'miter'];
ctx.lineWidth = 10;
for (var i = 0; i & #x3C; lineJoin.length; i++) {
ctx.lineJoin = lineJoin[i];
ctx.beginPath();
ctx.moveTo(-5, 5 + i * 40);
ctx.lineTo(35, 45 + i * 40);
ctx.lineTo(75, 5 + i * 40);
ctx.lineTo(115, 45 + i * 40);
ctx.lineTo(155, 5 + i * 40);
ctx.stroke();
}
A_Start > e3_lineJoin.html
miterLimit
ctx.miterLimit = 임계각; // 허용하는 최대 각
마이터(miter, 직각으로 물리는 톱니)의 구현에 있어서 어디까지 베블(bevel, 경사각)을 그려줄지 결정해야합니다.
A_Start > e4_miterLimit.html아래의 그림을 클릭합니다. miterLimit과 각도에 따라서 bevel을 그릴지 말지 결정합니다.
lineDash
주기를 무한히 반복합니다.
setLineDash([주기1, 주기2 ...]);A_Start > e5_linedash.html
lineDashOffset = 오프셋
애니메이션 기법은 Chapter 9에서 다시 다룹니다. 예제에서는 0.02초마다 march함수를 호출합니다. 부하가 걸리는 방식이기 때문에 추천하는 애니메이션은 아닙니다.
path2D
path2D객체로 경로를 가져와 그림을 그릴 수 있습니다.
new Path2D(); // empty path object
new Path2D(path); // copy from another Path2D object
new Path2D(d); // path from SVG path data
예제
// Path2D 객체를 생성한 후 그리기 예제
var drawing = new Path2D();
drawing.rect(10, 10, 50, 50);
drawing.moveTo(125, 35);
drawing.arc(100, 35, 25, 0, 2 * Math.PI);
ctx.fill(drawing);
// SVG 경로를 생성한 후 그리기 예제
// Move(200,10) → horizontal(수평) 80 이동 → vertical(수직) 80이동 → 수평 -40이동 → 원점으로
var p = new Path2D('M200 10 h 80 v 80 h -40 Z');
ctx.stroke(p);
A_Start > e6_path2D.html
Path표기법에 대해서는 "Svg > 그리기(path)"를 참조합니다