1. html
- canvas 태그 생성
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>canvas test</title>
</head>
<body>
<canvas></canvas>
</body>
</html>
2. css
body{
position: relative;
height: 100vh;
}
canvas {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
background-color:rgb(248 224 217);
}
3. javascript
1). 이미지 호출
- drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
매개변수(sx, sy)는 스프라이트 시트(소스)의 시작 위치,
(dx, dy)는 캔버스(대상)의 시작 위치며 기본적으로 왼쪽 상단이 (0, 0)에서 시작하여 오른쪽과 아래쪽으로 양수로 이동하는 그리드입니다.
"너비" 및 "높이" 매개변수( sWidth, sHeight)는 스프라이트 시트의 너비와 높이를
(dWidth및 dHeight)는 캔버스의 너비와 높이를 나타냅니다. 캔버스의 영역만큼 이미지를 가득 채워 확대시킵니다.
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 500;
canvas.height = 400;
let img = new Image(); //객체 생성
img.src = 'https://opengameart.org/sites/default/files/Green-Cap-Character-16x18.png';
img.onload = function() {
init();
};
function init() {
// future animation code goes here
ctx.drawImage(img, 0, 0, 16, 18, 20, 10, 16, 18);
// 소스이미지 안에 이미지는 16x18 출력
// 소스이미지에서 x, y, width, height , 캔버스 x, y, width, height
}
2). 이미지 호출
- drawImage( ) 변수값
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 500;
canvas.height = 400;
let img = new Image(); //객체 생성
img.src = 'https://opengameart.org/sites/default/files/Green-Cap-Character-16x18.png';
img.onload = function() {
init();
};
const scale = 2; //확대
const width = 16; //이미지 너비
const height = 18; //이미지 높이
const scaledWidth = scale * width;
const scaledHeight = scale * height;
function init() {
ctx.drawImage(img,
0, 0, width, height, 20, 10, scaledWidth, scaledHeight);
//0 , 0 , 16, 18, 20, 10, 32, 36
ctx.drawImage(img,
width, 0, width, height, scaledWidth + 20, 10, scaledWidth, scaledHeight);
//16 , 0 , 16, 18, 32+20 , 10, 32, 36
ctx.drawImage(img,
width * 2, 0, width, height, (scaledWidth * 2) + 20 , 10, scaledWidth, scaledHeight);
//16*2 , 0 , 16, 18, (32*2)+20, 10, 32, 36
}
3). 이미지 호출
- drawFrame( )
스프라이트 시트 수학을 처리하므로 프레임 번호만 전달하면 됩니다.
let img = new Image(); //객체 생성
img.src = 'https://opengameart.org/sites/default/files/Green-Cap-Character-16x18.png';
img.onload = function() {
init();
};
const scale = 2; //확대
const width = 16; //이미지 너비
const height = 18; //이미지 높이
const scaledWidth = scale * width;
const scaledHeight = scale * height;
const paddingLeft = 20;
const paddingTop = 10;
function drawFrame(frameX, frameY, canvasX, canvasY) {
ctx.drawImage(img,
frameX * width, frameY * height, width, height,
canvasX, canvasY, scaledWidth, scaledHeight);
}
function init() {
drawFrame(0, 0, paddingLeft, paddingTop);
drawFrame(1, 0, scaledWidth+paddingLeft, paddingTop);
drawFrame(0, 0, (scaledWidth * 2)+paddingLeft, paddingTop);
drawFrame(2, 0, (scaledWidth * 3)+paddingLeft, paddingTop);
}
4). 애니메이션
- equestAnimationFrame( ) 애니메이션 루프를 생성하기 위해 인수로 전달하는 재귀함수 입니다.
초당 60프레임으로 그려집니다.
function step() {
// do something
window.requestAnimationFrame(step);
}
- clearRect(x, y, 너비, 높이) 캔버스에서 지정된 픽셀을 지웁니다.
(노출되는 이미지 외의 이미지는 지우기 위해)
function drawFrame(frameX, frameY, canvasX, canvasY) {
ctx.drawImage(img,
frameX * width, frameY * height, width, height,
canvasX, canvasY, scaledWidth, scaledHeight);
}
const cycleLoop = [0, 1, 0, 2]; //노출 이미지
let i = 0; //이미지 index
function step() {
ctx.clearRect(0, 0, canvas.width, canvas.height); //선택 이외의 이미지 삭제
drawFrame(cycleLoop[i], 0, paddingLeft, paddingTop); //이미지 호출
i++;
if (i >= cycleLoop.length) { //이미지 반복
i = 0;
}
window.requestAnimationFrame(step);
}
4). 애니메이션_반복
- equestAnimationFrame( ) 초당 60프레임 -> 초당 15프레임
초당 0~15 프레임이 끝나야 새로운 이미지를 그릴 수 있습니다.
const cycleLoop = [0, 1, 0, 2];
let i = 0;
let frameCount = 0; //프레임 초기화
function step() {
frameCount++;
if (frameCount < 15) { //초당 0 ~ 15프레임
window.requestAnimationFrame(step);
return;
}
frameCount = 0; //프레임 초기화
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawFrame(cycleLoop[i], 0, paddingLeft, paddingTop);
i++;
if (i >= cycleLoop.length) {
i = 0;
}
window.requestAnimationFrame(step);
}
5). 애니메이션_반복 전환
-이미지 방향 전환을 위한 변수를 생성합니다.
const cycleLoop = [0, 1, 0, 2];
let i = 0;
let frameCount = 0;
let currentDirection = 0; //이미지 방향
function step() {
frameCount++;
if (frameCount < 15) {
window.requestAnimationFrame(step);
return;
}
frameCount = 0;
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawFrame(cycleLoop[i], currentDirection, paddingLeft, paddingTop); //frameY = currentDirection
i++;
if (i >= cycleLoop.length) {
i = 0;
currentDirection++;
}
if (currentDirection >= 4) {
currentDirection = 0;
}
window.requestAnimationFrame(step);
}
function init() {
window.requestAnimationFrame(step);
}
See the Pen sprite sheets animation_1 by gaae (@gaae) on CodePen.
참고:
https://dev.to/martyhimmel/animating-sprite-sheets-with-javascript-ag3
'JavaScript &jQuery' 카테고리의 다른 글
[JavaScript] Cannot read properties of null (0) | 2024.07.04 |
---|---|
[JavaScript] 스크롤 애니메이션 (Apple 제품 페이지) (0) | 2024.06.13 |
[JavaScript] 웹페이지 scroll이벤트 (0) | 2024.04.25 |
[JavaScript] style.setProperty() (0) | 2024.04.19 |