HTML5의 새로운 API, CANVAS는 웹 어플리케이션에 새로운 가능성을 열어주었습니다. 데스크탑, 모바일 앱에 버금가는 게임 등을 만들 수 있게해주었지요.

아래는 이런 기능을 구현하기위해 필요한 canvas에 그려진 shape, 도형을 이동시키는 방법에 대하여 알아보겠습니다.



# canvas 태그에 도형 그리고 이동시키기얼마 전 올린 포스팅에서 canvas의 클릭 이벤트를 사용해 도형 등의 오브젝트 이동 방법을 알아보았습니다. 간단한 예제였지만 이때 오브젝트를 이동하기 위해서 캔버스를 지우는 작업이 필요했지요...


! 이동시 캔버스를 지우고 다시 그리는 작업이 반드시 필요한가특정 오브젝트를 camvas에 그리고 이를 이동시키는 방법으로 전체를 지우거나 해당 영역을 지우고 다시 그리는 방법이 필요했습니다. 그럴 필요없이 이동시키는 방법은 없을까요? 현재까지의 CANVAS API만으로는 방법이 없어보입니다. 우리가 실제로 그림을 그렸을때 그 위의 대상을 이동시키려면 지우개 등을 이용해 지우고 다시 그려야하는 것처럼 canvas 역시 같은 작업이 필요하죠.

네... 생각해보면 매우 비효율적인 방법같습니다. 이동하는 물체가 하나 또는 두 개 정도라면 뭐 간단한 게임 정도 구현에 성능상 큰 이슈는 없겠지요... 하지만 이동해야할 물체가 많다면?? 아무래도 성능에 이슈가 생길 것이라 예상할 수 있겠죠.. 뭔가 방법이 없을까요?


! 여러개의 캔버스를 이용하기이때 사용 가능한 방법으로 여러개의 캔버스를 이용하는 방법이 존재합다. 즉 이동하는 물체마다 각각 서로 다른 캔버스를 사용하는 방법이지요. 이 방법이 가능한 이유는 canvas 영역이 transparency, 투명할 수 있기 때문인데 canvas를 겹쳐 사용한다면 이동할때마다 전체 캔버스를 지울 필요없이 해당 오브젝트를 가진 캔버스민 선택하여 지우고 이동할 수 있겠지요. 생각해보면 가장 그럴싸한 방법이지요? 더 나은 방법이 있다면 모르겠지만 현재까지는 가장 효과적인 장법이라 생각됩니다.



# 여러개의 canvas 사용하여 오브젝트(shape) 이동 예제그럼 위의 방법대로 여러개의 오브젝트를 이동하는데 복수개의 canvas 태그를 사용하여 아래 예제에서 구현해보겠습니다. 아래의 예제는 위에서 낙하하는 물체와 좌에서 우로 이동하는 오브젝트를 만들어보았습니다.

<div class="canvas-wrap">
  <canvas id="ball" width="300" height="600"></canvas>
  <canvas id="bucket" width="300" height="600"></canvas>
</div>
<input type="button" value="click" onclick="start();" />

위 두 개의 canvas는 서로 겹치도록 해야겠죠. 아래처럼 css를 적용합니다.
.canvas-wrap {
  position: relative;
  width: 300px;
  height: 600px;
  border: 1px solid #000;
}
canvas {
  position: absolute;
}

이제 캔버스에서 이동하는 오브젝트를 각각의 canvas에서 구현해야합니다. 각각의 canvas에서 구현할 기능입니다.

#ball
위에서 공이 자유낙하

#bucket

dropBall = function() {
  var canvas = document.querySelector('canvas#ball');
  var ctx = canvas.getContext('2d');

  var x = getRandom(300);
  for (var i = 0; i < 600; i++) {
    draw(x, i);
  }

  function draw(x, y) {
    setTimeout(function() {
      ctx.clearRect(0, 0, 300, 600);
      ctx.beginPath();
      ctx.arc(x, y, 20, 0, Math.PI * 2, true);
      ctx.fill();
    }, 5 * y);
  }
}


drawBucket = function() {
  var canvas = document.querySelector('canvas#bucket');
  var ctx = canvas.getContext('2d');

  for (var i = 0; i < 1200; i++) {
    draw(i);
  }

  function draw(x) {
    setTimeout(function() {
      ctx.clearRect(0, 0, 300, 600)
      ctx.beginPath();
      x = x % 300;
      ctx.fillRect(x, 550, 50, 30);
    }, 3 * x);
  }
}


function getRandom(range) {
  return Math.floor(range * Math.random());
}


start = function() {
  dropBall();
  drawBucket();
}


여기까지 코드가 완성되었습니다.


# 예제 동작해보기위의 코드가 어떻게 동작하는지 아래에 구현해두었습니다. 직접 버튼을 클릭하여 수행해보세요.