const canvas = document.getElementById('canvas1'); const ctx = canvas.getContext('2d'); const originalImageWidth = 500; const originalImageHeight = 500; const imageAspectRatio = originalImageWidth / originalImageHeight; function setCanvasSize() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } let effect; class Particle { constructor(effect, x, y) { this.effect = effect; this.originX = x; this.originY = y; this.relativeX = x - effect.centerX; this.relativeY = y - effect.centerY; this.x = Math.random() * canvas.width; this.y = Math.random() * canvas.height; this.size = 4; this.color = "CC9900"; this.dx = 0; this.dy = 0; this.vx = 0; this.vy = 0; this.force = 0; this.angle = 0; this.distance = 0; this.friction = 0.98; this.ease = 0.19; this.shakeStrength = 0.5; } update() { this.originX = this.effect.centerX + this.relativeX * this.effect.scale; this.originY = this.effect.centerY + this.relativeY * this.effect.scale; this.dx = this.effect.mouse.x - this.x; this.dy = this.effect.mouse.y - this.y; this.distance = this.dx * this.dx + this.dy * this.dy; this.force = -this.effect.mouse.radius / this.distance; if(this.distance < this.effect.mouse.radius) { this.angle = Math.atan2(this.dy, this.dx); this.vx += this.force * Math.cos(this.angle); this.vy += this.force * Math.sin(this.angle); } let returnForce = 0.001; this.vx += (this.originX - this.x) * returnForce; this.vy += (this.originY - this.y) * returnForce; this.x += this.vx; this.y += this.vy; this.vx *= this.friction; this.vy *= this.friction; this.x += (Math.random() - 0.5) * this.shakeStrength; this.y += (Math.random() - 0.5) * this.shakeStrength; } } class Effect { constructor(ctx) { this.ctx = ctx; this.image = document.getElementById('image'); this.particles = []; this.gap = 8; this.maxWidth = 500; this.maxHeight = 500; this.mouse = { radius: 1000, x: 0, y: 0 } window.addEventListener("mousemove", event => { this.mouse.x = event.x; this.mouse.y = event.y; }); window.addEventListener("touchstart", event => { this.mouse.x = event.changedTouches[0].clientX; this.mouse.y = event.changedTouches[0].clientY; }, false); window.addEventListener("touchmove", event => { event.preventDefault(); this.mouse.x = event.targetTouches[0].clientX; this.mouse.y = event.targetTouches[0].clientY; }, false); window.addEventListener("touchend", event => { event.preventDefault(); this.mouse.x = 0; this.mouse.y = 0; }, false); } init() { this.ctx.clearRect(0, 0, canvas.width, canvas.height); this.centerX = canvas.width / 2; this.centerY = canvas.height / 2; this.scale = Math.min( Math.min(this.maxWidth / originalImageWidth, this.maxHeight / originalImageHeight), Math.min(0.9 * canvas.width / originalImageWidth, canvas.height / originalImageHeight) ); this.width = originalImageWidth * this.scale; this.height = originalImageHeight * this.scale; this.x = this.centerX - this.width / 2; this.y = this.centerY - this.height / 2; this.ctx.drawImage(this.image, this.x, this.y, this.width, this.height); const pixels = this.ctx.getImageData(0, 0, canvas.width, canvas.height).data; this.particles = []; let index; for(let y = 0; y < canvas.height; y += this.gap) { for(let x = 0; x < canvas.width; x += this.gap) { index = (y * canvas.width + x) * 4; if(pixels[++index] > 0) { this.particles.push(new Particle(this, x, y)); } } } this.ctx.clearRect(0, 0, canvas.width, canvas.height); } update() { for(let i = 0; i < this.particles.length; i++) { this.particles[i].update(); } } render() { this.ctx.clearRect(0, 0, canvas.width, canvas.height); for(let i = 0; i < this.particles.length; i++) { let p = this.particles[i]; let lightColor = p.color.replace('rgb', 'rgba').replace(')', ', 0.5)'); this.ctx.fillStyle = lightColor; this.ctx.fillRect(p.x, p.y, p.size, p.size); } } } function setup() { setCanvasSize(); effect = new Effect(ctx); effect.init(); } document.addEventListener("DOMContentLoaded", function() { setup(); animate(); window.addEventListener('resize', setup); }); function animate() { effect.update(); effect.render(); requestAnimationFrame(animate); }