mdn의 캔버스 튜토리얼 따라하기
참고 : 캔버스 튜토리얼
파노라마
* ********************************
* 파노라마
* *********************************
*/
var img = new Image();
// 변수
img.src = "images/shinee_concert.jpg";
var CanvasXSize;
var CanvasYSize;
var speed = 1; // 애니메이션 업데이트 속도
var scale = 0.5;
var y = 0; // 수직 옵셋
var dx = 0.75; // 캔버스에서의 이동량(음수 왼쪽, 양수 오른쪽)
var imgW;
var imgH;
var x = 0; // 이미지 위치
var clearX;
var clearY;
var ctx;
img.onload = () => {
// 캔버스 요소 열기
ctx = document.getElementById("canvas3").getContext("2d");
CanvasXSize = ctx.canvas.width;
CanvasYSize = ctx.canvas.height;
// 이미지 크기 조정
imgW = img.width * scale;
imgH = img.height * scale;
// 이미지가 캔버스보다 크면 초기 위치 조정
// 오른쪽으로 흘러가므로 시작 위치는 이미지의 오른쪽 끝
if(imgW > CanvasXSize) {
x = CanvasXSize - imgW;
}
// 캔버스 비우기 사이즈
/* 굳이 비교해서 가져오는 이유는
* 1. 이미지 크기에 따라 캔버스 크기가 동적으로 전환될 수 있음
* 2. 이미지의 일부분만 클리어하지 않도록 보장
*/
clearX = Math.max(imgW, CanvasXSize);
clearY = Math.max(imgH, CanvasYSize);
// 화면 갱신 속도 설정
return setInterval(drawAnni2, speed);
}
function drawAnni2() {
// 캔버스 비우기
ctx.clearRect(0,0,clearX, clearY);
// 이미지가 캔버스보다 작거나 같다면
if(imgW <= CanvasXSize) {
// 재설정, 처음부터 시작
if(x > CanvasXSize) {
x = -imgW + x;
}
// 추가 이미지 그리기
if(x > 0) {
ctx.drawImage(img, -imgW + x, y, imgW, imgH);
}
if(x - imgW > 0) {
ctx.drawImage(img, -imgW * 2 + x, y, imgW, imgH);
}
} else {
// 이미지가 캔버스보다 크다면
if(x > CanvasXSize) {
x = CanvasXSize - imgW;
}
// 추가 이미지 그리기
if(x > CanvasXSize - imgW) {
ctx.drawImage(img, x - imgW + 1, y, imgW, imgH);
}
}
// 이미지 그리기
ctx.drawImage(img, x, y, imgW, imgH);
// 움직임 정도
x += dx;
}
마우스 따라오는 애니메이션
/* ********************************
* mouse following animation
* *********************************
*/
const cwCanvas = document.getElementById("cw");
const context = cwCanvas.getContext("2d");
context.globalAlpha = 0.5;
// 마우스커서 초기값
const cursor = {
x: innerWidth / 2,
y: innerHeight / 2,
};
console.log('innerWidth', innerWidth);
let particlesArray = [];
generateParticles(101);
setSize(); // 캔버스 크기 설정
anim();
// 마우스 움직임 이벤트시 좌표값 설정
addEventListener("mousemove", (e) => {
cursor.x = e.clientX;
cursor.y = e.clientY;
});
// 터치 이동 시 기본 동작 막고 cursor 객체 좌표값 업데이트
addEventListener(
"touchmove",
(e) => {
e.preventDefault(); // 기본 동작 실행하지 않도록 지정
cursor.x = e.touches[0].clientX;
cursor.y = e.touches[0].clientY;
},
{ passive: false },
);
// 창 크기 조절시 캔버스 크기 재조정
addEventListener("resize", () => setSize());
function generateParticles(amount) {
for(let i=0; i<amount; i++) {
particlesArray[i] = new Particle(
innerWidth / 2,
innerHeight / 2,
4,
generateColor(),
0.02,
);
}
}
function generateColor() {
let hexSet = "0123456789ABCDEF";
let finalHexString = "#";
for(let i=0; i<6; i++) {
finalHexString += hexSet[Math.ceil(Math.random() * 15)];
}
return finalHexString;
}
function setSize() {
cwCanvas.height = 500;
cwCanvas.width = 500;
}
// 입자(초기 위치, 꼬리 너비, 색상, 회전 속도)
function Particle(x, y, particleTrailWidth, strokeColor, rotateSpeed) {
this.x = x;
this.y = y;
this.particleTrailWidth = particleTrailWidth;
this.strokeColor = strokeColor;
this.theta = Math.random() * Math.PI * 2;
this.rotateSpeed = rotateSpeed;
this.t = Math.random() * 150;
this.rotate = () => {
// 입자의 이전 위치
const ls = {
x: this.x,
y: this.y,
};
this.theta += this.rotateSpeed; // 회전각도
this.x = cursor.x + Math.cos(this.theta) * this.t;
this.y = cursor.y + Math.sin(this.theta) * this.t;
this.y -= 300;
context.beginPath();
context.lineWidth = this.particleTrailWidth;
context.strokeStyle = this.strokeColor;
context.moveTo(ls.x, ls.y);
context.lineTo(this.x, this.y);
context.stroke();
};
}
function anim() {
requestAnimationFrame(anim);
context.fillStyle = "rgb(0 0 0 / 5%)";
context.fillRect(0, 0, cwCanvas.width, cwCanvas.height);
particlesArray.forEach((particle) => particle.rotate());
}
'Frontend > HTML' 카테고리의 다른 글
[HTML/Canvas] 공 움직이기 애니메이션(basic ver) (1) | 2024.02.27 |
---|---|
[HTML/canvas] 장애물을 피해 마우스 움직이기 게임 (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 |