💙 들어가며
오늘부터는 본격적으로 플랫폼을 사용해서
자바스크립트 언어를 활용한 다양한 입출력을 경험해보자!
✏️ 학습내용 정리
#Canvas API
일단 기본적으로 사용할 것은 Canvas 플랫폼이다.
Canvas API란 HTML 문서에 그래픽을 추가하기 위한 API이다.
Canvas 외에도 그래픽을 지원하는 SVG나 다양한 API들이 존재한다.
그 중에서도 Canvas는 가장 Raw한 그래픽 API로서 활용도가 높지만 모든 것을 처음부터 다 구현해야 한다.
(별, 그림자 모든 것을 Path 하나로 다 구현해야 함)
때문에 그 Raw한 점이 큰 장점이자 동시에 단점이 될 수도 있겠다.
canvas는 자체의 기본 크기를 가지고 있어서 그 크기가 넘는 그림을 그리면 짤리게 된다.
그러면 크기를 어떻게 조정할 수 있을까?
canvas의 크기는 css의 style로 키우는 것이 아니다.
HTML에서 직접 크기를 조정한다.
잘 구분하면서 사용해야겠다.
❌ 잘못된 방법
style을 통해서 크기를 주었다.
<canvas id="canvas" style="width:600px; height:300px"></canvas>
⭕ 옳은 방법
HTML 태그 자체에 width와 height를 설정했다.
<canvas id="canvas" width="600" height="300"></canvas>
⭕ 출력결과:
잘못된 방법:

옳은 방법:

그리고, defer옵션을 주지 않으면 script가 body보다 먼저 나올 때
id값을 찾지 못해서 오류가 난다. (순서의 문제!)
💡 script에 defer을 붙여야만 맨 마지막에 실행된다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="canvas.js" defer></script>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
💡 canvas.js의 내용
var ctx = canvas.getContext("2d");
console.log(ctx);
⭕ 출력결과:
head에 script를 넣어놓았고, body에 canvas 내용을 넣어놨는데도
head에 있는 script가 body내용을 잘 인식해서 오류가 나지 않는다!
#유효성검사
생각보다 구형 컴퓨터를 사용하는 경우가 있을 수 있어서
캔버스를 사용하기 전에는 구현이 가능한지 검사가 필요하다.
(그렇지만 요새는 거의 canvas는 기본으로 지원되는 경우가 대다수라서 걱정할 필요 X)
canvas.getContext를 했을 때 false가 나오면 canvas를 그릴 수 없다.
#도형 그리기 연습
그럼 canvas를 이용해서 다양한 도형을 그려보자.
일단 기본적으로 알아야 할 것은 canvas는 사각형만 함수를 이용해서 그릴 수 있다.
canvas는 사각형을 제외한 모든 도형은 path를 이용해서 그려야 한다.
#사각형 그리기
그럼 먼저 사각형을 그려보자.
총 4개의 인자가 필요한데, 차례대로 (x좌표, y좌표, 너비, 높이)이다.
💡 다음을 출력하면?
ctx.fillRect(10, 10, 50, 50);
ctx.fillRect(30, 30, 50, 50);
⭕ 출력결과:
사각형 2개 그리기 성공!

조금 더 심화버전으로 여러 버전의 사각형을 그릴 수 있다.
먼저 3가지 사각형의 차이점을 확인해보자.
fillRect를 하면 기본적으로 검은색 사각형이 만들어지는데
fillStyle을 통해서 여러가지 색깔을 줄 수 있다.
clearRect를 하면 하얀색 사각형이 만들어지기 때문에
사각형 안에 내용을 지우고 싶은 것이 있다면 clearRect를 사용하여 지울 수 있겠다.
이때 clearRect는 style을 먹일 수 없다.
그냥 흰색으로만 만들 수 있다는 점을 기억하자.
그리고 선으로만 그린 사각형은 strokeRect를 통해서 만들어볼 수 있겠다.
💡 다음을 출력하면?
ctx.fillStyle = 'rgba(200,0,0,0.5)';
ctx.fillRect(100, 100, 50, 50);
ctx.fillStyle = "rgba(0,0,200,0.5)";
ctx.fillRect(120, 120, 50, 50);
ctx.clearRect(130, 130, 30, 30);
ctx.strokeRect(135, 135, 20, 20);
⭕ 출력결과:
빨간색 사각형과 파란색 사각형을 그렸다.
특히 파란색 사각형은
fill, clear, stroke를 활용해서 3개의 사각형을 그려보았다.

#캔바스에 색을 줄 때
위에 이미 한 번 언급하였지만, fillstyle이라는 함수를 활용하여
CSS에서 많이 사용해보았던 rbga()를 대입하면 된다.
fillStyle을 적용하지 않으면 기본 색상은 검은색으로 적용이 된다.
마지막 4번째 인자는 알파값으로 불투명도를 조절할 때 사용한다.
#선을 활용해서 도형 만들기
사각형이 아닌 다양한 도형도 그려보자.
여기서 fill과 stroke로 그리는 도형에는 차이점이 있다.
fill을 할 때는 열린 모양으로 좌표가 끝나도 자동으로 닫아주지만
stroke로 선을 그릴 때에는 closePath()를 해줘야 한다.
단순히 선만 그릴 때는 moveTo(), lineTo()만 해서는 그어지지 않는다.
마지막에 stroke()를 해줘야 한다.
무슨말일까? 삼각형을 그리면서 감을 익혀보자.
💡 다음을 출력하면?
ctx.beginPath();
ctx.moveTo(75, 50);
ctx.lineTo(100, 75);
ctx.lineTo(100, 25);
ctx.fill();
⭕ 출력결과:
1) moveTo(75,50) 좌표에서 시작한다.
2) lineTo(100,75)위치로 이동하면서 선을 긋는다.
3) lineTo(100,25)위치로 이동하면서 선을 긋는다.
4) fill()을 하니 자동으로 1지점으로 마지막점이 이동하면서 삼각형이 완성되었다.

사각형과 삼각형을 활용해서 그림을 그려보자!
💡 다음을 출력하면?
ctx.fillStyle = "rgba(0,0,100, 0.5)"
ctx.fillRect(25, 25, 100, 100);
ctx.clearRect(45, 45, 60, 60);
ctx.strokeRect(50, 50, 50, 50);
ctx.beginPath(); // 펜을 누르고
ctx.moveTo(75, 50); // 이동하고
ctx.lineTo(100, 75); // 그린다.
ctx.lineTo(75, 100); // 그린다.
ctx.lineTo(50, 75); // 그린다.
// ctx.closePath(); // 자동으로 선을 닫는다.
// ctx.stroke(); // 선을 그린다.
ctx.fill(); // 색을 채운다.
⭕ 출력결과:
fill()을 하면 자동으로 path가 닫히지만
stroke를 하면 closePath()를 먼저 해줘야 한다는 차이가 있다.

#arc와 path를 이용해서 눈사람 만들기
beginPath()와 moveTo(), arc()를 이용해서 다음과 같은 눈사람을 만들어 볼 수 있다.
Path가 계속해서 이어지기 때문에 중간 중간에 moveTo()를 잘 이용해야 한다.
마지막에 ctx.stroke()를 꼭 해줘야 한다!
💡 다음을 출력하면?
console.log("=====원 그리기=====");
ctx.beginPath();
ctx.arc(75, 75, 50, 0, Math.PI * 2, true); // Outer circle
ctx.moveTo(110, 75);
ctx.arc(75, 75, 35, 0, Math.PI, false); // Mouth (clockwise)
//===============================
ctx.moveTo(80, 75)
ctx.arc(75, 75, 5, 0, Math.PI * 2, false);
ctx.moveTo(61, 60);
ctx.arc(55, 60, 6, 0, Math.PI * 2, false); // 왼쪽눈
ctx.moveTo(101, 60);
ctx.arc(95, 60, 6, 0, Math.PI * 2, false); // 오른쪽눈
ctx.moveTo(150, 200);
ctx.arc(75, 200, 75, 0, Math.PI * 2, false); // 몸통
ctx.moveTo(80, 200);
ctx.arc(75, 200, 5, 0, Math.PI * 2, false); // 단추2
ctx.moveTo(80, 160);
ctx.arc(75, 160, 5, 0, Math.PI * 2, false); // 단추1
ctx.moveTo(80, 240)
ctx.arc(75, 240, 5, 0, Math.PI * 2, false); // 단추3
ctx.stroke();
⭕ 출력결과:
귀여운 눈사람 그리기 성공!

#quadraticCurve(1포인트) 와 bezierCurve(2포인트)
quadraticCurve
위에 점이 하나 있다고 생각하고 그 점으로 라인이 휘는 곡선을 그려보자.
💡 다음을 출력하면?
console.log("=====쿼드라곡선 그리기=====")
ctx.beginPath();
ctx.moveTo(50, 50);
ctx.quadraticCurveTo(150, 10, 100, 100);
ctx.stroke();
ctx.strokeRect(150, 10, 1, 1);
⭕ 출력결과:
한 점을 따라 선이 가운데로 휘어진 모습이 그려진다.

bezierCurve
위에 점이 두개 있다고 생각하고 그 점으로 라인이 휘는 곡선을 그려보자.
💡 다음을 출력하면?
console.log("=====베지어곡선 그리기=====")
ctx.beginPath();
ctx.moveTo(50, 50);
ctx.bezierCurveTo(150, 10, 150, 70, 100, 100)
ctx.stroke();
ctx.strokeRect(150, 10, 1, 1);
ctx.strokeRect(150, 70, 1, 1);
⭕ 출력결과:
두 점을 따라서 선이 휜 모습으로 그려진다.

#Path2D
각각의 도형으로 만들어나가는 방법
각각 객체를 생성해서 만들기 때문에
moveTo() lineTo()처럼 하나로 이어서 만드는 것보다 훨씬 만들기가 쉽다.
💡 다음을 출력하면?
console.log("=====2D로 그림 그리기=====")
ctx.strokeStyle = "rgba(0,0,200, 0.5)"
var shape1 = new Path2D();
shape1.rect(10, 10, 100, 100);
ctx.stroke(shape1);
var shape2 = new Path2D();
shape2.arc(160, 60, 50, 0, 2 * Math.PI);
ctx.stroke(shape2);
⭕ 출력결과:
사각형과 원형이 각각 만들어졌다.

인자로 받아서 한 번에 만드는 방법도 있다.
💡 다음을 출력하면?
console.log("=====2D로 그림 그리기=====")
var shape3 = new Path2D("M10 10 h 110 v 100 h -110 v -100");
ctx.stroke(shape3);
⭕ 출력결과:
마지막 shape3에서 (M: move 좌표이동 h: 수평이동 v: 수직이동)을 의미한다.
똑같이 사각형을 그릴 수 있음

💙 마치며
Path2D를 잘 활용하면
손쉽게 원하는 모양을 만들 수 있을 것 같다.
좌표에 대한 감을 잘 익히고
Path를 잘 활용할 줄 알아야겠다.