UNPKG

aura-glass

Version:

A comprehensive glassmorphism design system for React applications with 142+ production-ready components

241 lines (239 loc) 7.03 kB
const DEFAULT_CONFIG = { magneticEffect: true, magneticStrength: 0.3, magneticRange: 50, rippleEffect: true, rippleColor: 'var(--glass-border-hover)', rippleDuration: 600, hoverGlow: true, glowColor: 'var(--glass-color-primary, 0.4)', glowIntensity: 0.6, physicsAnimations: true, springConfig: { stiffness: 200, damping: 25, mass: 1 } }; const GalileoElementInteractionPlugin = { id: 'galileoElementInteraction', defaults: DEFAULT_CONFIG, beforeInit: (chart, args, options) => { const config = { ...DEFAULT_CONFIG, ...options }; // Store configuration on chart instance chart.galileoConfig = config; chart.galileoState = { hoveredElement: null, activeElements: new Map(), ripples: [], mousePosition: { x: 0, y: 0 } }; }, afterInit: (chart, args, options) => { const canvas = chart.canvas; const config = chart.galileoConfig; const state = chart.galileoState; // Mouse move handler for magnetic effects const handleMouseMove = event => { const rect = canvas.getBoundingClientRect(); const x = event.clientX - rect.left; const y = event.clientY - rect.top; state.mousePosition = { x, y }; if (config.magneticEffect) { updateMagneticEffects(chart, x, y); } if (config.hoverGlow) { updateHoverGlow(chart, x, y); } chart.update('none'); }; // Click handler for ripple effects const handleClick = event => { if (!config.rippleEffect) return; const rect = canvas.getBoundingClientRect(); const x = event.clientX - rect.left; const y = event.clientY - rect.top; createRipple(chart, x, y); }; // Mouse leave handler const handleMouseLeave = () => { state.hoveredElement = null; state.activeElements.clear(); chart.update('none'); }; canvas.addEventListener('mousemove', handleMouseMove); canvas.addEventListener('click', handleClick); canvas.addEventListener('mouseleave', handleMouseLeave); // Store cleanup function chart.galileoCleanup = () => { canvas.removeEventListener('mousemove', handleMouseMove); canvas.removeEventListener('click', handleClick); canvas.removeEventListener('mouseleave', handleMouseLeave); }; }, beforeDestroy: chart => { const cleanup = chart.galileoCleanup; if (cleanup) cleanup(); }, afterDraw: (chart, args, options) => { const ctx = chart.ctx; const state = chart.galileoState; const config = chart.galileoConfig; // Draw ripples if ((state.ripples?.length || 0) > 0) { drawRipples(ctx, state.ripples); updateRipples(state.ripples, config.rippleDuration); } // Draw hover glow if (state.hoveredElement) { drawHoverGlow(ctx, state.hoveredElement, config); } // Draw magnetic effects if (config.magneticEffect && state.activeElements.size > 0) { drawMagneticEffects(ctx, state.activeElements); } } }; // Helper functions function updateMagneticEffects(chart, mouseX, mouseY) { const config = chart.galileoConfig; const state = chart.galileoState; const meta = chart.getDatasetMeta(0); if (!meta || !meta.data) return; meta.data?.forEach((element, index) => { const centerX = element.x; const centerY = element.y; const distance = Math.sqrt((mouseX - centerX) ** 2 + (mouseY - centerY) ** 2); if (distance <= config.magneticRange) { const influence = 1 - distance / config.magneticRange; const deltaX = (mouseX - centerX) * config.magneticStrength * influence; const deltaY = (mouseY - centerY) * config.magneticStrength * influence; state.activeElements.set(index, { originalX: centerX, originalY: centerY, currentX: centerX + deltaX, currentY: centerY + deltaY, influence }); // Apply magnetic offset element.x = centerX + deltaX; element.y = centerY + deltaY; } else { // Reset to original position if (state.activeElements.has(index)) { const original = state.activeElements.get(index); element.x = original.originalX; element.y = original.originalY; state.activeElements.delete(index); } } }); } function updateHoverGlow(chart, mouseX, mouseY) { const state = chart.galileoState; const meta = chart.getDatasetMeta(0); if (!meta || !meta.data) return; let closestElement = null; let minDistance = Infinity; meta.data?.forEach((element, index) => { const distance = Math.sqrt((mouseX - element.x) ** 2 + (mouseY - element.y) ** 2); if (distance < minDistance && distance <= 20) { // 20px hover radius minDistance = distance; closestElement = { element, index, distance }; } }); state.hoveredElement = closestElement; } function createRipple(chart, x, y) { const state = chart.galileoState; const config = chart.galileoConfig; const ripple = { x, y, radius: 0, maxRadius: 100, opacity: 1, startTime: Date.now(), color: config.rippleColor }; state.ripples.push(ripple); } function drawRipples(ctx, ripples) { ripples.forEach(ripple => { ctx.save(); ctx.globalAlpha = ripple.opacity; ctx.strokeStyle = ripple.color; ctx.lineWidth = 2; ctx.beginPath(); ctx.arc(ripple.x, ripple.y, ripple.radius, 0, Math.PI * 2); ctx.stroke(); ctx.restore(); }); } function updateRipples(ripples, duration) { const now = Date.now(); for (let i = (ripples?.length || 0) - 1; i >= 0; i--) { const ripple = ripples[i]; const elapsed = now - ripple.startTime; const progress = elapsed / duration; if (progress >= 1) { ripples.splice(i, 1); } else { ripple.radius = ripple.maxRadius * progress; ripple.opacity = 1 - progress; } } } function drawHoverGlow(ctx, hoveredElement, config) { if (!hoveredElement) return; const { element } = hoveredElement; ctx.save(); ctx.globalAlpha = config.glowIntensity; ctx.shadowColor = config.glowColor; ctx.shadowBlur = 20; ctx.fillStyle = config.glowColor; ctx.beginPath(); ctx.arc(element.x, element.y, 8, 0, Math.PI * 2); ctx.fill(); ctx.restore(); } function drawMagneticEffects(ctx, activeElements) { activeElements.forEach((elementData, index) => { const { originalX, originalY, currentX, currentY, influence } = elementData; // Draw connection line ctx.save(); ctx.globalAlpha = influence * 0.3; ctx.strokeStyle = 'var(--glass-border-hover)'; ctx.lineWidth = 1; ctx.setLineDash([2, 4]); ctx.beginPath(); ctx.moveTo(originalX, originalY); ctx.lineTo(currentX, currentY); ctx.stroke(); ctx.restore(); }); } export { GalileoElementInteractionPlugin, GalileoElementInteractionPlugin as default }; //# sourceMappingURL=GalileoElementInteractionPlugin.js.map