UNPKG

realm-loader-npm

Version:

A comprehensive collection of 14 beautiful circle animations with performance optimization, presets, themes, and React/Vue components

112 lines (87 loc) 4.43 kB
import { BaseAnimation } from './BaseAnimation' import { PulsingGridConfig } from '../types' export class PulsingGridAnimation extends BaseAnimation { private gridSize: number private spacing: number private breathingSpeed: number private waveSpeed: number private colorPulseSpeed: number constructor(container: HTMLElement, config: PulsingGridConfig = {}) { super(container, config) this.gridSize = config.gridSize || 5 this.spacing = config.spacing || 15 this.breathingSpeed = config.breathingSpeed || 0.5 this.waveSpeed = config.waveSpeed || 1.2 this.colorPulseSpeed = config.colorPulseSpeed || 1.0 } protected draw(): void { const centerX = this.canvas.width / 2 const centerY = this.canvas.height / 2 // Calculate breathing effect - grid expands and contracts const breathingFactor = Math.sin(this.time * this.breathingSpeed) * 0.2 + 1.0 // Center dot removed for cleaner look // Draw pulsing grid pattern for (let row = 0; row < this.gridSize; row++) { for (let col = 0; col < this.gridSize; col++) { // Skip center point if (row === Math.floor(this.gridSize / 2) && col === Math.floor(this.gridSize / 2)) continue // Calculate base position const baseX = (col - (this.gridSize - 1) / 2) * this.spacing const baseY = (row - (this.gridSize - 1) / 2) * this.spacing // Calculate distance and angle from center for effects const distance = Math.sqrt(baseX * baseX + baseY * baseY) const maxDistance = (this.spacing * Math.sqrt(2) * (this.gridSize - 1)) / 2 const normalizedDistance = distance / maxDistance const angle = Math.atan2(baseY, baseX) // Apply complex wave effects const radialPhase = (this.time - normalizedDistance) % 1 const radialWave = Math.sin(radialPhase * Math.PI * 2) * 4 const spiralPhase = (angle / (Math.PI * 2) + this.time * 0.3) % 1 const spiralWave = Math.sin(spiralPhase * Math.PI * 2) * 3 const breathingX = baseX * breathingFactor const breathingY = baseY * breathingFactor const waveX = centerX + breathingX + Math.cos(angle) * radialWave const waveY = centerY + breathingY + Math.sin(angle) * radialWave const baseSize = 1.5 + (1 - normalizedDistance) * 1.5 const pulseFactor = Math.sin(this.time * 2 + normalizedDistance * 5) * 0.6 + 1 const size = baseSize * pulseFactor // Color effects - subtle gradient between white and light blue const blueAmount = Math.sin(this.time * this.colorPulseSpeed + normalizedDistance * 3) * 0.3 + 0.3 const whiteness = 1 - blueAmount const r = Math.floor(255 * whiteness + 200 * blueAmount) const g = Math.floor(255 * whiteness + 220 * blueAmount) const b = 255 const opacity = 0.5 + Math.sin(this.time * 1.5 + angle * 3) * 0.2 + normalizedDistance * 0.3 // Draw connecting lines if (row > 0 && col > 0 && row < this.gridSize - 1 && col < this.gridSize - 1) { const neighbors = [ { r: row - 1, c: col }, { r: row, c: col + 1 }, { r: row + 1, c: col }, { r: row, c: col - 1 } ] for (const neighbor of neighbors) { const nBaseX = (neighbor.c - (this.gridSize - 1) / 2) * this.spacing const nBaseY = (neighbor.r - (this.gridSize - 1) / 2) * this.spacing const nBreathingX = nBaseX * breathingFactor const nBreathingY = nBaseY * breathingFactor if (neighbor.r === Math.floor(this.gridSize / 2) && neighbor.c === Math.floor(this.gridSize / 2)) continue const lineDistance = Math.sqrt(Math.pow(col - neighbor.c, 2) + Math.pow(row - neighbor.r, 2)) const lineOpacity = 0.1 + Math.sin(this.time * 1.5 + lineDistance * 2) * 0.05 this.ctx.beginPath() this.ctx.moveTo(waveX, waveY) this.ctx.lineTo(centerX + nBreathingX, centerY + nBreathingY) this.ctx.strokeStyle = `rgba(255, 255, 255, ${lineOpacity})` this.ctx.lineWidth = 0.5 this.ctx.stroke() } } // Draw dot this.ctx.beginPath() this.ctx.arc(waveX, waveY, size, 0, Math.PI * 2) this.ctx.fillStyle = `rgba(${r}, ${g}, ${b}, ${opacity})` this.ctx.fill() } } } }