Javascript
Canvas Crash Effect 기록(react + typescript)
YoYoHa
2022. 12. 7. 18:00
728x90
반응형
Mouse Crash Effect Code 기록
import React, {useEffect, useRef} from 'react';
interface mouseType {
x?: number,
y?: number
}
export default function Crash(){
const canvasRef = useRef<HTMLCanvasElement>(null);
const mouse: mouseType = { x: undefined, y: undefined }
const particlesArray: any = [];
let hue:number = 0;
useEffect(() => {
const canvas = canvasRef?.current;
if (canvas) {
let ctx = canvas.getContext('2d');
class Particle {
private x: number | undefined;
private y: number | undefined;
private size: number | undefined;
private readonly speedX: number | undefined;
private readonly speedY: number | undefined;
private readonly color: string | undefined;
constructor() {
if (canvas) {
this.x = mouse.x;
this.y = mouse.y;
this.size = Math.random() * 15 + 1;
this.speedX = Math.random() * 3 - 1.5;
this.speedY = Math.random() * 3 - 1.5;
this.color = 'hsl(' + hue + ', 100%, 50%)'
}
}
update() {
if ( this.x && this.y && this.speedX && this.speedY ) {
this.x += this.speedX;
this.y += this.speedY;
if (typeof this.size === 'number') if (this.size > 0.2) this.size -= 0.1;
}
}
draw() {
if (ctx) {
if (typeof this.color === 'string') ctx.fillStyle = this.color;
ctx.beginPath();
if (typeof this.size === "number") {
ctx.arc(this.x as number, this.y as number, this.size, 0, Math.PI * 2);
}
ctx.fill();
}
}
}
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
if (ctx) {
const animate = () => {
if (ctx) {
ctx.clearRect(0,0, canvas.width, canvas.height);
// ctx.fillStyle = 'rgba(0,0,0,0.02)';
// ctx.fillRect(0,0, canvas.width, canvas.height);
handleParticles();
hue+=2;
requestAnimationFrame(animate);
}
};
const handleParticles = () => {
for (let i=0;i<particlesArray.length;i++){
particlesArray[i].update();
particlesArray[i].draw();
for(let j =i;j<particlesArray.length;j++) {
const dx = particlesArray[i].x - particlesArray[j].x;
const dy = particlesArray[i].y - particlesArray[j].y;
const distance = Math.sqrt(dx*dx+dy*dy);
if (distance < 100 && ctx) {
ctx.beginPath();
ctx.strokeStyle = particlesArray[i].color;
ctx.lineWidth = 0.5;
ctx.moveTo(particlesArray[i].x, particlesArray[i].y)
ctx.lineTo(particlesArray[j].x, particlesArray[j].y)
ctx.stroke();
ctx.closePath();
}
}
if (particlesArray[i].size <= 0.3) {
particlesArray.splice(i, 1);
i--;
}
}
};
window.addEventListener('resize', () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
});
canvas.addEventListener('click', (e) => {
mouse.x = e.x;
mouse.y = e.y;
for (let i=0;i < 5; i++) {
particlesArray.push(new Particle());
}
});
canvas.addEventListener('mousemove', (e) => {
console.log('111');
mouse.x = e.x;
mouse.y = e.y;
for (let i=0;i < 3; i++) {
particlesArray.push(new Particle());
}
console.log(particlesArray);
});
animate();
} else {
console.log('null ctx');
}
}
}, []);
return (
<canvas className="canvas" ref={canvasRef}></canvas>
);
};
.canvas{ position: absolute; z-index: 1; background: black; width: 100%; height: 100%; top: 0; left: 0; }
728x90
반응형