canvas를 사용해 방향키로 좌우 이동 조작할 수 있는 캐릭터를 만들어보았습니다. 움직이는 캐릭터의 이전 모습을 삭제하기 위해 배경과 캐릭터의 캔버스를 나누어 진행하였습니다.

canvas 캐릭터 방향키로 좌우 이동하기

 

 목차

 

1. 구현 화면

2. 고려사항

3. 구현

4. 구현된 코드로 보기

 

1. 구현 화면

방향키를 통해 좌우 이동하는 캐릭터

2. 고려사항

  • 하나의 캔버스만 사용할 시 이전 캐릭터의 그림들을 삭제하기 어려움
    • 이전 캐릭터의 그림을 지우기 위해 해당 좌표를 clearRect로 지울 시 배경까지 같이 삭제되어 버림
    • 따라서, 배경, 캐릭터를 레이어로 나누어 구현
    • 배경은 바닥에, 캐릭터는 공중에 뜬 상태로 그려진다고 볼 수 있음

3. 구현

  • 배경 이미지를 넣을 canvas, 캐릭터를 넣을 canvas 2개 생성
  • 배경 canvas와 캐릭터 canvas가 겹쳐져야 하므로 상위 태그에는 relative, canvas에는 absolute 속성 부여

 

<!-- index.html -->

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <!-- 배경 이미지를 넣을 canvas, 캐릭터를 넣을 canvas 2개 생성 -->
    <!-- 배경 canvas와 캐릭터 canvas가 겹쳐져야 하므로 상위 태그에는 relative, canvas에는 absolute 속성 부여 -->
    <div style="position: relative;">
      <canvas id="background" style="position: absolute;"></canvas>
      <canvas id="character" style="position: absolute;"></canvas>
    </div>
    <script src="maple.js"></script>
  </body>
</html>

 

  • 배경 canvas 지정
  • 캐릭터 canvas 지정
  • 배경 제작
    • 배경 경로 불러오기
    • 배경 이미지를 불러오면 배경 canvas에 그리기
    • 이미지를 불러오는 과정에서 비율이 깨지지 않게 이미지의 가로, 세로 길이를 그대로 canvas에 지정
  • 캐릭터 제작
    • 캐릭터 경로 불러오기
    • 캐릭터의 x 좌표 지정
    • 캐릭터 불러오면 캐릭터 canvas에 그리기
    • 캐릭터가 이동할 수 있는 반경은 배경 내부 이므로 배경 이미지의 가로, 세로 길이를 그대로 canvas에 지정
  • canvas에서 키입력 이벤트 설정
    • 캐릭터의 좌표가 0이하면 더이상 왼쪽으로 이동 못하게 제한
    • "캐릭터의 x 좌표 값 + 캐릭터의 가로 길이"가 배경의 가로 길이보다 커질 시 더이상 오른쪽으로 이동 못하게 제한

 

// maple.js

// 배경 canvas 지정
const backgroundCanvas = document.getElementById("background");
const backCtx = backgroundCanvas.getContext("2d");

// 캐릭터 canvas 지정
const characterCanvas = document.getElementById("character");
const chaCtx = characterCanvas.getContext("2d");

// 배경 경로 불러오기
const port = new Image();
port.src =
  "https://github.com/ka0824/ka0824.github.io/assets/79782594/e264a9fb-541b-4cd4-845b-947385a19cef";

// 배경 이미지를 불러오면 배경 canvas에 그리기
// 이미지를 불러오는 과정에서 비율이 깨지지 않기 위해 이미지의 가로, 세로 길이를 그대로 canvas에 적용
port.onload = function () {
  backgroundCanvas.width = port.width;
  backgroundCanvas.height = port.height;
  backCtx.drawImage(port, 0, 0);
};

// 캐릭터 경로 불러오기
const mushroom = new Image();
mushroom.src =
  "https://github.com/ka0824/ka0824.github.io/assets/79782594/1cac660c-db2c-46d0-af9a-ecfebe31b62d";

// 캐릭터의 x 좌표 지정
let mushroomX = 0;

// 캐릭터 불러오면 캐릭터 canvas에 그리기
// 캐릭터가 이동할 수 있는 반경은 배경 내부 이므로 배경 이미지의 가로, 세로 길이를 그대로 적용
mushroom.onload = function () {
  characterCanvas.width = port.width;
  characterCanvas.height = port.height;
  chaCtx.drawImage(mushroom, mushroomX, 100, 40, 50);
};

// canvas에서 키입력 이벤트 설정
document.addEventListener("keydown", function (event) {
  switch (event.key) {
    case "ArrowLeft":
      // 캐릭터의 좌표가 0 이하면 더이상 왼쪽으로 이동 못하게 제한
      if (mushroomX <= 0) {
        return;
      }

      // 이동 속도는 -10, 이동할 때 마다 이전 이미지 지워주기
      mushroomX -= 10;
      chaCtx.clearRect(0, 0, characterCanvas.width, characterCanvas.height);
      chaCtx.drawImage(mushroom, mushroomX, 100, 40, 50);
      return;
    case "ArrowRight":
      // 캐릭터의 가로축이 40이므로, '현재 캐릭터의 x 좌표 값 + 40'이 배경의 가로축보다 커지면 오른쪽으로 이동 못하게 제한
      if (mushroomX + 40 >= characterCanvas.width) {
        return;
      }

      mushroomX += 10;
      chaCtx.clearRect(0, 0, characterCanvas.width, characterCanvas.height);
      chaCtx.drawImage(mushroom, mushroomX, 100, 40, 50);
      return;
    default:
      return;
  }
});

4. 구현된 코드로 보기

'javascript > canvas' 카테고리의 다른 글

canvas로 간단 애니메이션 구현하기  (0) 2023.10.09
캔버스로 기본 도형(2d) 그리기  (0) 2023.10.08

canvas로 애니메이션을 구현해보겠습니다. 좌표를 어떻게 변경해야 할지 고려해 봅시다.

canvas로 간단 애니메이션 구현하기

 

 목차

 

1. 알아두기

2. 직선 이동 애니메이션

3. 원모양 이동 애니메이션

4. 반복되는 애니메이션

5. 왕복 이동 애니메이션

6. 구현 코드로 보기

추천글

 

1. 알아두기

  • x, y 좌표로 이동시키기
    • canvas의 애니메이션은 애니메이션의 x, y좌표를 변경하면서 진행됨
    • 연속되는 그림이 빠르게 지나가면서 애니메이션으로 보여진다라고 생각할 수 있음

 

  • 애니메이션의 속도는 좌표 변경 값의 크기에 따라 정해짐
    • 좌표 변경 값이 클 수록 속도가 빨라지고, 변경 값이 작을 수록 속도가 느려짐

 

  • 이전 화면이 필요 없다면 clearRect 메서드를 이용해 canvas를 지우기
    • clearRect를 사용하지 않으면 이전 화면도 그대로 남아있음. 상황에 따라 사용 여부 결정할 것.

 

  • requestAnimationFrame 함수를 이용하자
    • 작성한 애니메이션 함수를 requestAnimationFrame을 이용해 애니메이션으로 구현할 수 있음

2. 직선 이동 애니메이션

  • 애니메이션 시작 좌표 정하기
  • 좌표 증가 값 정하기 (애니메이션의 속도)
  • 애니메이션 함수 작성
    • 좌표 증가 시키기
    • 달라진 좌표에 맞춰 그림 그리기
    • 애니메이션 맞춤 설정
// lineAnimation.js

const canvas1 = document.getElementById("my-canvas1");
const ctx1 = canvas1.getContext("2d");

// 애니메이션 시작 좌표 정하기
let startX1 = 10;
let startY1 = 10;

const dx1 = 10;

function lineAnimation() {
  // 캔버스 지우기
  // 캔버스의 width, height 값 입력
  ctx1.clearRect(0, 0, canvas1.width, canvas1.height);

  ctx1.fillStyle = "black";

  // 좌표 증가 시키기
  startX1 += dx1;

  // 달라진 좌표에 맞춰서 그림 그리기
  ctx1.fillRect(startX1, startY1, 100, 100);

  // 애니메이션 맞춤 설정
  requestAnimationFrame(lineAnimation);
}

lineAnimation();

3. 원모양 이동 애니메이션

 

  • 시작 각도 지정
  • 각도 늘어나는 값 지정 (애니메이션 속도)
  • 애니메이션 함수 작성
    • 원의 중심 좌표 업데이트
    • 코사인(cos), 사인(sin)을 이용해  x 좌표, y 좌표를 반지름에 맞춰 비율 조정
      • cos(각도) = b / c
      • sin(각도) = a / c
      • 현재 각도에서 생성된 b와 c의 비율 값을 통해 원 외곽의 x 좌표 구하기
      • 현재 각도에서 생성된 a와 c의 비율 값을 통해 원 외곽의 y 좌표 구하기
      • 생성된 x, y 좌표에 경로의 둘레를 얼마나 크게 할 것 인지 값 설정
원 외곽의 x, y 좌표를 구하는 과정
cos(각도) = b / c, 가로 b를 사용하므로 x좌표에 사용

 

sin(각도) = a / c, 세로 a를 사용하므로 y 좌표에 사용

 

// circleAnimation.js

const canvas2 = document.getElementById("my-canvas2");
const ctx2 = canvas2.getContext("2d");

let startX2 = 50;
let startY2 = 50;

// 각도 지정
let angle = 0;

// 애니메이션 속도, 각도가 늘어나는 값
const speed = 0.1;

function circleAnimation() {
  ctx2.clearRect(0, 0, canvas2.width, canvas2.height);

  ctx2.beginPath();

  ctx2.arc(startX2, startY2, 10, 0, 2 * Math.PI);

  ctx2.fillStyle = "white";
  ctx2.fill();
  ctx2.strokeStyle = "black";
  ctx2.lineWidth = 2;
  ctx2.stroke();

  angle += speed;

  // 원의 중심 좌표 업데이트
  // 코사인, 사인을 이용해 x 좌표, y 좌표를 반지름에 맞춰 비율 조정
  // 뒤에 곱하는 값이 커질수록 경로의 둘레가 커짐
  startX2 = 50 + Math.cos(angle) * 40;
  startY2 = 50 + Math.sin(angle) * 40;

  // 다음 프레임 요청
  requestAnimationFrame(circleAnimation);
}

circleAnimation();

 

4. 반복되는 애니메이션

 

  • 직선 이동 애니메이션 재활용
  • 애니메이션 그림이 화면을 벗어나게 되면 좌표 초기화
// infiniteAnimation.js

const canvas3 = document.getElementById("my-canvas3");
const ctx3 = canvas3.getContext("2d");

let startX3 = 10;
let startY3 = 10;
let dx3 = 10;

function infiniteAnimation() {
  ctx3.clearRect(0, 0, canvas3.width, canvas3.height);

  ctx3.fillStyle = "black";

  // 화면을 벗어나게 되면 좌표 초기화
  if (startX3 === canvas3.width) {
    startX3 = 10;
  } else {
    startX3 += dx3;
  }

  ctx3.fillRect(startX3, startY3, 100, 100);

  requestAnimationFrame(infiniteAnimation);
}

infiniteAnimation();

5. 왕복 이동 애니메이션

  • 직선 이동 애니메이션 재활용
  • 이동 방향 결정하는 변수 추가
  • 특정 지점에 도달할 때마다 이동 방향 변경
  • 이동 방향에 따라 좌표 증감
// leftRightAnimation.js

const canvas4 = document.getElementById("my-canvas4");
const ctx4 = canvas4.getContext("2d");

let startX4 = 10;
let startY4 = 10;

let dx4 = 10;

// 이동 방향 결정하는 변수 추가
let isMoveRight = true;

function leftRightAnimation() {
  ctx4.clearRect(0, 0, canvas4.width, canvas4.height);

  ctx4.fillStyle = "black";

  // 특정 지점에 도달할 때마다 이동 방향 변경
  if (startX4 + 100 === canvas4.width) {
    isMoveRight = false;
  } else if (startX4 === 10) {
    isMoveRight = true;
  }

  // 이동 방향에 따라 좌표 증감
  if (isMoveRight) {
    startX4 += dx4;
  } else {
    startX4 -= dx4;
  }

  ctx4.fillRect(startX4, startY4, 100, 100);

  requestAnimationFrame(leftRightAnimation);
}

leftRightAnimation();

6. 구현 코드로 보기

추천글

2023.10.08 - [javascript/canvas] - 캔버스로 기본 도형(2d) 그리기

 

캔버스로 기본 도형(2d) 그리기

캔버스는 웹 페이지에 그래픽을 그리는 데에 사용되며, 이미지, 그래프, 애니메이션 등 시각적 요소를 생성하고 조작할 수 있습니다. 이 포스팅에서는 캔버스를 이용해 2d 기본 도형을 그리는 방

ddmoonddmoon.tistory.com

 

 

'javascript > canvas' 카테고리의 다른 글

canvas 캐릭터 방향키로 좌우 이동하기  (1) 2023.10.12
캔버스로 기본 도형(2d) 그리기  (0) 2023.10.08

 캔버스는 웹 페이지에 그래픽을 그리는 데에 사용되며, 이미지, 그래프, 애니메이션 등 시각적 요소를 생성하고 조작할 수 있습니다. 이 포스팅에서는 캔버스를 이용해 2d 기본 도형을 그리는 방법을 알아보겠습니다.

캔버스로 기본 도형(2d) 그리기

 

 목차

 

1. 캔버스란?

2. 직선 그리기

3. 사각형 그리기

4. 삼각형 그리기

5. 곡선 그리기

6. 원 그리기

7. 구현된 코드로 보기

 

1. 캔버스란?

  • 웹 페이지에 그래픽을 그리는 데 사용
  • 이미지, 그래프, 애니메이션, 게임에 활용 가능
  • 빠른 그래픽 렌더링으로 고성능
  • 복잡한 시각적 효과, 애니메이션에 적용 가능

 

  • 캔버스 생성하기
    • canvas 생성 후, id를 이용해 canvas 변수에 할당하기
    • canvas에서 ctx 가져오기
   <canvas id="my-canvas1" width="400" height="400"></canvas>
   
   <script>
   	
    // canvas 변수에 할당하기
 	const canvas1 = document.getElementById("my-canvas1");
    
    // "context"의 약자로, 캔버스의 요소를 조작할 때 사용
	const ctx1 = canvas1.getContext("2d");
   </script>

2. 직선 그리기

  • 시작점, 끝점 좌표 정하기
  • 선 설정하기
  • 좌표 이으면서 선 그리기
const canvas1 = document.getElementById("my-canvas1");
const ctx1 = canvas1.getContext("2d");

// 시작점, 끝점 좌표 정하기
const startX = 50;
const startY = 50;
const endX = 100;
const endY = 100;

// 선 설정 정하기
ctx1.strokeStyle = "black";
ctx1.lineWidth = 2;

// 선 그리기 시작
ctx1.beginPath();

// 시작점 설정
ctx1.moveTo(startX, startY);

// 끝점 설정
ctx1.lineTo(endX, endY);

// 선 그리기
ctx1.stroke();

3. 사각형 그리기

  • 사각형 스타일 설정하기
  • 사각형 위치, 크기 설정하기
    • ctx.fillRect(x 좌표,  y 좌표, 가로 길이, 세로 길이)
    • fillRect는 색이 채워진 사각형, strokeRect는 테두리만 그려진 사각형이 그려짐
const canvas2 = document.getElementById("my-canvas2");
const ctx2 = canvas2.getContext("2d");

// 사각형 스타일 설정

// 채우기 색상
ctx2.fillStyle = "black"; 

// 테두리 색상
ctx2.strokeStyle = "black"; 

// 테두리 두께
ctx2.lineWidth = 2; 

// 사각형 그리기
// x 좌표, y 좌표, 가로 크기, 세로 크기
// 색깔 채워진 사각형
ctx2.fillRect(50, 50, 100, 100); 

// 테두리만 있는 사각형
ctx2.strokeRect(50, 150, 100, 100);

4. 삼각형 그리기

  • 삼각형의 세 꼭지점 좌표 정한 후 이어주기
const canvas3 = document.getElementById("my-canvas3");
const ctx3 = canvas3.getContext("2d");

ctx3.beginPath();

// 시작점
ctx3.moveTo(100, 50);

// 두번째 점
ctx3.lineTo(150, 150);

// 세번째 점
ctx3.lineTo(50, 150); 

// 경로 닫기
ctx3.closePath(); 

// 테두리 색상
ctx3.strokeStyle = "black"; 

// 테두리 두께
ctx3.lineWidth = 2; 

// 삼각형 채울 색상
ctx3.fillStyle = "blue"; 

// 삼각형 내부 색상 채우기
ctx3.fill(); 

// 삼각형 테두리 그리기
ctx3.stroke();

5. 곡선 그리기

  • quadraticCurveTo() 혹은 bezierCurveTo() 함수 사용
    • quadraticCurveTo(곡선 제어점 x 좌표, 곡선 제어점 y 좌표, 최종 x 좌표, 최종 y좌표)
    • bezierCurveTo(1차 곡선 제어점 x 좌표, 1차 곡선 제어점 y 좌표, 2차 제어점 x, 2차 제어점 y, 최종  x, 최종 y)
const canvas4 = document.getElementById("my-canvas4");
const ctx4 = canvas4.getContext("2d");

ctx4.beginPath();

// 시작점 정하기
ctx4.moveTo(50, 50);

// 두 개의 제어점을 사용한 곡선 그리기
// 첫번째로 꺾을 지점 x 좌표, y좌표, 2번째로 꺾을 지점 x 좌표, y 좌표, 최종 x 좌표, y 좌표
ctx4.bezierCurveTo(50, 100, 150, 20, 250, 50);

ctx4.strokeStyle = "black";
ctx4.lineWidth = 2;

// 곡선을 테두리로 그리기
ctx4.stroke();

6. 원 그리기

  • arc 메서드 사용
    • arc(중심 x 좌표, 중심 y좌표, 반지름, 원의 시작 각도, 원의 끝 각도)
    • 시작 각도, 끝 각도를 통해 원의 일부만 그릴 수도 있음
const canvas5 = document.getElementById("my-canvas5");
const ctx5 = canvas5.getContext("2d");

ctx5.beginPath();

// 중심 x 좌표,  중심 y, 좌표, 반지름, 원의 시작 각도, 원의 끝 각도
// 시작각도, 끝각도를 통해 원의 일부만 그릴 수도 있음
ctx5.arc(100, 100, 50, 0, 2 * Math.PI);

ctx5.fillStyle = "white";
ctx5.fill();
ctx5.strokeStyle = "black";
ctx5.lineWidth = 2;
ctx5.stroke();

7. 구현된 코드로 보기

+ Recent posts