태양을 중심으로 지구, 지구를 중심으로 달을 움직이는 애니메이션을 만들어보았다. 코딩으로하는 애니메이션에 대해서 그동안 감이 좀없고 낮설었는데, (특히 게임 스크립팅도...) 익숙해질겸 건드려보고있는데 이거...재밌다..ㅋㅋㅋㅋㅋㅋ
우선 매 프레임마다 모든 요소를 다시그려주어야한다. 어렸을때 책 귀퉁이에 한장 한장마다 그려서 쭈루루룩 넘기면서 애니메이션을 만들었던것처럼, 다음장을 넘기고 그리고를 반복한다.
반복
윈도우가 로드되면, 루프를 시작한다. 이 루프는 일정한 프레임마다 영원히 돌면서 update()를 실행시키게 된다.
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
window.onload = () => {
loop();
}
function loop() {
// 계속해서 애니메이션 진행
setInterval(update, 1000 / 20); // 20FPS 프레임 속도
}
지우고, 그리기
update()에서는 매번 그림을 지우고, 다시 그린다. clearRect()로 캔버스 전체를 지우고, draw...()로 그 시점에서의 태양과 지구, 달을 그려준다.
function update() {
// 이전에 그림을 지우고 다시 그림
context.clearRect(0, 0, canvas.width, canvas.height);
drawSun();
const [earthDx, earthDy] = drawEarth();
drawMoon(earthDx, earthDy);
}
지구만 이해하면 OK
삼각함수 포스팅에서 P(x1, y1)의 위치를 알고 싶을때 x1 = cos(θ) * r, y1 = sin(θ) * r로 정리된다고 앞서 살펴보았다. 지구의 다음 위치가 바로 P(x1, y1)이되고, 지구와 태양사이의 거리가 r이된다. 그리고 나서는 currentDegree를 증가시킴으로서 θ값을 키워 점차 돌아가게 만들 수 있다.
달은 지구를 중심으로 돌아야하는데, 지구의 좌표를 이미 계산했으니 그 값을 반환해서 지구의 좌표를 중심으로 달의 좌표를 계산할 수 있도록 했다.
function drawEarth() {
var distanceFromSun = 100;
context.beginPath();
// 캔버스의 중간지점 + 삼각비에 길이를 곱해주면 된다.
var dx = (canvas.width / 2) + Math.cos(deg2Rad(currentDegree)) * distanceFromSun;
var dy = (canvas.height / 2) + Math.sin(deg2Rad(currentDegree)) * distanceFromSun;
var radius = 10;
context.arc(dx, dy, radius, 0, 2 * Math.PI);
context.lineWidth = 5;
context.fillStyle = "lightseagreen";
context.fill();
context.strokeStyle = "green";
context.stroke();
currentDegree++;
// 달을 위해 지구의 현재 위치를 반환
return [dx, dy];
}
전체 소스
<!DOCTYPE html>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
canvas {
background: #111111;
}
</style>
<body>
<canvas id="canvas" width="500" height="320"/>
</body>
<script>
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var currentDegree = 0; // 태양에 대한 지구의 위치(각도)
var currentMoonDegree = 0; // 지구에 대한 달의 위치(각도)
window.onload = () => {
loop();
}
function loop() {
// 계속해서 애니메이션 진행
setInterval(update, 1000 / 20); // 20FPS 프레임 속도
}
function update() {
// 이전에 그림을 지우고 다시 그림
context.clearRect(0, 0, canvas.width, canvas.height);
drawSun();
const [earthDx, earthDy] = drawEarth();
drawMoon(earthDx, earthDy);
}
function drawSun() {
context.beginPath();
// 태양의 위치는 캔버스 중간
var dx = canvas.width / 2;
var dy = canvas.height / 2;
var radius = 30;
context.arc(dx, dy, radius, 0, 2 * Math.PI);
context.fillStyle = "yellow"
context.fill();
context.lineWidth = 5;
context.strokeStyle = "orange";
context.stroke();
}
function drawEarth() {
var distanceFromSun = 100;
context.beginPath();
// 캔버스의 중간지점 + 삼각비에 길이를 곱해주면 된다.
var dx = (canvas.width / 2) + Math.cos(deg2Rad(currentDegree)) * distanceFromSun;
var dy = (canvas.height / 2) + Math.sin(deg2Rad(currentDegree)) * distanceFromSun;
var radius = 10;
context.arc(dx, dy, radius, 0, 2 * Math.PI);
context.lineWidth = 5;
context.fillStyle = "lightseagreen";
context.fill();
context.strokeStyle = "green";
context.stroke();
currentDegree++;
// 달을 위해 지구의 현재 위치를 반환
return [dx, dy];
}
function drawMoon(earthDx, earthDy) {
var distanceFromEarth = 20;
context.beginPath();
var dx = earthDx + Math.cos(deg2Rad(currentMoonDegree)) * distanceFromEarth;
var dy = earthDy + Math.sin(deg2Rad(currentMoonDegree)) * distanceFromEarth;
var radius = 3;
context.arc(dx, dy, radius, 0, 2 * Math.PI);
context.lineWidth = 5;
context.strokeStyle = "white";
context.stroke();
// 지구의 공전속도보다 훨씬 빠르게
currentMoonDegree += 12;
}
function deg2Rad(degree) {
return Math.PI / 180 * degree;
}
</script>
</html>
'프로그래밍 > JS, Node.js' 카테고리의 다른 글
[Next.js] process.env가 undefined로 나올때 (0) | 2022.06.25 |
---|---|
네이버 카페 댓글 사진 일괄 다운받는 방법 (0) | 2022.05.23 |
DOMContentLoaded와 jQuery document.ready()의 중요한 차이점 (0) | 2021.10.31 |
React JS 개념 잡기 - 빠르게 한 번 훑어보고 싶다면 (0) | 2021.01.08 |
[Node.js] Selenium 사용법을 익혀보자 (11) | 2021.01.03 |