본문 바로가기
front-end/html&css

[HTML5/Canvas] Canvas 공부 1일차 : x축 기본 애니메이션까지

by MOOB 2020. 12. 6.

Canvas Day1

Canvas란

Canvas는 HTML5에서 새로 추가된 태그 중 하나로, 페이지에 그래픽 요소를 추가할 때 주로 사용된다. 기본적으로 width, height 속성을 가지고 있는데 이는 레이아웃이 랜더링되어 있기 때문에 CSS로 임의로 크기를 지정할 경우 화면이 왜곡되어 보일 수 있어 비율을 맞춰주어야 한다.

아래 두개의 canvas는 겉으로 보기에는 같은 크기이나 실제 화면에 이미지를 그렸을 때 차이가 난다.

image

Canvas는 일반적인 이미지 속성과 같이 margin, border 등을 줄 수 있지만 실제 캔버스에 그리는 그림에는 영향을 미치지 않는다.

<canvas id="board_canvas" width="500" height="500"></canvas>

기본적인 사각형 그리기

var canvas = document.getElementById("board_canvas");
    var ctx = canvas.getContext("2d");
    ctx.fillStyle = "black";
    ctx.fillRect(100, 100, 100, 100); //색 채워진 사각형
    ctx.strokeRect(150, 150, 100, 100); // 테두리 가진 사각형
    ctx.clearRect(30, 30, 100, 100); // 설정한 부분만큼 삭제

!

image

원그리기

원은 그냥 그릴 수 없고 arc() 라는 호 그리기 함수를 사용해서 사용해야 한다.

image

var canvas = document.getElementById("board_canvas");
    var ctx = canvas.getContext("2d");
    ctx.fillStyle = "black";
    ctx.arc(100, 75, 50, 0, 2 * Math.PI); //(x, y, 반지름, 시작점, 끝점)
    ctx.fill(); //ctx.stroke()

수학 그만둔지 너무 오래되서... 맨 마지막 끝점은 radian 단위로 들어가야 하는데(호로 원을 만든 것이기 때문이다!)360도가 2 * Math.PI 이고 만약 Math.PI 가 들어가면 반원이 된다.

함수로 만들어서 이해를 도운 버전

image

function radian(degree) {
      return (degree * Math.PI) / 180;
    }
    var canvas = document.getElementById("board_canvas");
    var ctx = canvas.getContext("2d");
    ctx.fillStyle = "black";
    ctx.arc(100, 75, 50, 0, radian(320)); //(x, y, 반지름, 시작점, 끝점)
    ctx.stroke(); //ctx.stroke()

이제 무엇이든 그릴 수 있을 것 같지만 사실 이거 한 붓 그리기다. 만약 다음과 같은 코드를 짠다면 붓을 떼는 동작을 지정해 주지 않았기 때문에 다음과 같은 그림이 나온다.

function radian(degree) {
      return (degree * Math.PI) / 180;
    }
    var canvas = document.getElementById("board_canvas");
    var ctx = canvas.getContext("2d");
    ctx.fillStyle = "black";
    ctx.arc(100, 75, 50, 0, radian(320));
    ctx.arc(200, 75, 50, 0, radian(320)); //(x, y, 반지름, 시작점, 끝점)
    ctx.stroke(); //ctx.stroke()

image

그러므로 이것을 한 붓 그리기로 하지 않기 위해서는 시작 지점을 ctx.beginPath() 를 통해 매 번 다시 지정해 주어야 한다.

function radian(degree) {
      return (degree * Math.PI) / 180;
    }
    var canvas = document.getElementById("board_canvas");
    var ctx = canvas.getContext("2d");
        ctx.fillStyle = "black";
        ctx.beginPath(); //시작점 그려!
    ctx.arc(100, 75, 50, 0, radian(320)); // 위치!
    ctx.stroke();// 위에 쓴대로 그려!
    ctx.beginPath(); // 여기서 다시 시작!
    ctx.arc(200, 75, 50, 0, radian(320)); // 위치2222
    ctx.stroke(); // 다시 그려!

image

이거 좀 성가시지 않나..? 좀... 너무.... 노가다 아닌가...?

애니메이션 만들기 : x축 따라 날라가는 공

var canvas = document.getElementById("board_canvas");
    var ctx = canvas.getContext("2d");
    ctx.fillStyle = "black";

    let xPos = 10;

    function draw() {
      ctx.clearRect(0, 0, canvas.width, canvas.height); // 전체 지우기
      ctx.beginPath(); //새로 그리기~
      ctx.arc(xPos, 150, 20, 0, Math.PI * 2);
      ctx.fill();
      xPos += 3;
      requestAnimationFrame(draw); //루프를 통해 매번 새로그림
    }
    draw(); // or setInterval(draw, 10) => 최적화 및 프레임 유실 xxx

함수로 더 느리게 가게 한 버전

var canvas = document.getElementById("board_canvas");
    var ctx = canvas.getContext("2d");
    ctx.fillStyle = "black";
    let count = 0;

    let xPos = 10;

    function draw() {
      if (count % 3 === 0) {
        ctx.clearRect(0, 0, canvas.width, canvas.height); // 전체 지우기
        ctx.beginPath(); //새로 그리기~
        ctx.arc(xPos, 150, 20, 0, Math.PI * 2);
        ctx.fill();
        xPos += 3;
      }
      count++;
      requestAnimationFrame(draw); //루프를 통해 매번 새로그림
    }
    draw();

날아가는 공 멈추게 하기


    //방법 1

    var canvas = document.getElementById("board_canvas");
    var ctx = canvas.getContext("2d");
    ctx.fillStyle = "black";
    let xPos = 10;

    function draw() {
      ctx.clearRect(0, 0, canvas.width, canvas.height); // 전체 지우기
      ctx.beginPath(); //새로 그리기~
      ctx.arc(xPos, 150, 10, 0, Math.PI * 2);
      ctx.fill();
      xPos += 1;
      if (xPos >= canvas.width - 10) {
        return; //  return 해줌으로서 밑의 request...가 실행 안됨
      }
      requestAnimationFrame(draw); //루프를 통해 매번 새로그림
    }
    draw();

    //방법 2

    var canvas = document.getElementById("board_canvas");
    var ctx = canvas.getContext("2d");
    ctx.fillStyle = "black";
    let xPos = 10;
    let time;

    function draw() {
      ctx.clearRect(0, 0, canvas.width, canvas.height); // 전체 지우기
      ctx.beginPath(); //새로 그리기~
      ctx.arc(xPos, 150, 10, 0, Math.PI * 2);
      ctx.fill();
      xPos += 1;

      time = requestAnimationFrame(draw); //루프를 통해 매번 새로그림
      if (xPos >= canvas.width - 10) {
        cancelAnimationFrame(time);
      }
    }
    draw();

클릭했을 때 멈추게 하기

var canvas = document.getElementById("board_canvas");
    var ctx = canvas.getContext("2d");
    ctx.fillStyle = "black";
    let xPos = 10;
    let time;

    function draw() {
      ctx.clearRect(0, 0, canvas.width, canvas.height); // 전체 지우기
      ctx.beginPath(); //새로 그리기~
      ctx.arc(xPos, 150, 10, 0, Math.PI * 2);
      ctx.fill();
      xPos += 1;

      time = requestAnimationFrame(draw); //루프를 통해 매번 새로그림
    }
    draw();

    canvas.addEventListener("click", () => {
      cancelAnimationFrame(time);
    });

댓글