공 움직이기 애니메이션(basic ver)
mdn의 캔버스 튜토리얼 따라하기
참고 : 캔버스 튜토리얼
1. 공 그리기
HTML
<canvas id="canvas" width="600" height="300"></canvas>
JS
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const ball = {
// 초기 위치
x: 100,
y: 100,
// 속도
vx: 5,
vy: 1,
radius: 25,
color: "blue",
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fillStyle = this.color;
ctx.fill();
},
};
ball.draw();
2. 속도 추가
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
let raf; // 애니메이션 제어
const ball = {
x: 100,
y: 100,
vx: 5,
vy: 2,
radius: 25,
color: "blue",
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fillStyle = this.color;
ctx.fill();
},
};
function draw() {
// 프레임 지우기
ctx.clearRect(0, 0, canvas.width, canvas.height);
ball.draw();
// 공 이동
ball.x += ball.vx;
ball.y += ball.vy;
raf = window.requestAnimationFrame(draw);
}
canvas.addEventListener("mouseover", (e) => {
raf = window.requestAnimationFrame(draw);
});
canvas.addEventListener("mouseout", (e) => {
window.cancelAnimationFrame(raf);
});
ball.draw();
3. 경계
경계 추가 코드
🔺y축을 예시로 충돌 검사하는 방법
function draw() {
// 프레임 지우기
ctx.clearRect(0, 0, canvas.width, canvas.height);
ball.draw();
// 공 이동
ball.x += ball.vx;
ball.y += ball.vy;
// 충돌방지
if (
ball.y + ball.vy > canvas.height - ball.radius || // 바닥 충돌 감지
ball.y + ball.vy < ball.radius // 천장 충돌 감지
) {
ball.vy = -ball.vy; // 수직 방향 반전
}
if(
ball.x + ball.vx > canvas.width - ball.radius ||
ball.x + ball.vx < ball.radius
) {
ball.vx = -ball.vx;
}
raf = window.requestAnimationFrame(draw);
}
4. 가속
ball.vy *= 0.99; // 수직 속고 감속, 부드러운 움직임
ball.vy += 0.25; // 수직 속도에 외력 추가
5. 후행효과
ctx.fillStyle = "rgb(255 255 255 / 30%)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
🔺불투명도 0일 때
🔺불투명도 30일 때
불투명도가 점점 올라가면서 잔상과 같은 효과가 남.
6. 마우스 컨트롤 추가(최종 코드)
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
let raf; // 애니메이션 제어
let running = false; // 공 애니메이션 진행 여부
const ball = {
// 초기 위치
x: 100,
y: 100,
// 속도
vx: 5,
vy: 1,
radius: 25,
color: "blue",
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fillStyle = this.color;
ctx.fill();
},
};
function clear() {
// 후행효과(잔상)
ctx.fillStyle = "rgb(255 255 255 / 30%)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
function draw() {
// 프레임 지우기
//ctx.clearRect(0, 0, canvas.width, canvas.height);
clear();
ball.draw();
// 공 이동
ball.x += ball.vx;
ball.y += ball.vy;
//가속
ball.vy *= 0.99; // 수직 속고 감속, 부드러운 움직임
ball.vy += 0.25; // 수직 속도에 외력 추가
// 충돌방지
if (
ball.y + ball.vy > canvas.height - ball.radius || // 바닥 충돌 감지
ball.y + ball.vy < ball.radius // 천장 충돌 감지
) {
ball.vy = -ball.vy; // 수직 방향 반전
}
if(
ball.x + ball.vx > canvas.width - ball.radius ||
ball.x + ball.vx < ball.radius
) {
ball.vx = -ball.vx;
}
raf = window.requestAnimationFrame(draw);
}
canvas.addEventListener("mousemove", (e) => {
if(!running) {
clear();
// 캔버스 위치에 따라 오차가 남 엘리먼트 밖 여백 제거한 후 위치로 세팅
ball.x = e.clientX - canvas.getBoundingClientRect().left;
ball.y = e.clientY - canvas.getBoundingClientRect().top;
ball.draw();
}
});
canvas.addEventListener("click", (e) => {
if(!running) {
raf = window.requestAnimationFrame(draw);
running = true;
}
});
// canvas.addEventListener("mouseover", (e) => {
// raf = window.requestAnimationFrame(draw);
// });
canvas.addEventListener("mouseout", (e) => {
window.cancelAnimationFrame(raf); // 애니메이션 중지
running = false;
});
ball.draw();
'Frontend > HTML' 카테고리의 다른 글
[HTML/canvas] 장애물을 피해 마우스 움직이기 게임 (0) | 2024.02.26 |
---|---|
[HTML/canvas] Basic animations(2/2) (0) | 2024.02.26 |
[HTML/canvas] Basic animations(1/2) (0) | 2024.02.22 |
[HTML/canvas] Compositing and clipping (0) | 2024.02.22 |
[HTML/canvas] 변형 (transformations) (1) | 2024.02.22 |