UNPKG

aura-glass

Version:

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

327 lines (325 loc) 11 kB
// Easing functions const easingFunctions = { linear: t => t, easeInQuad: t => t * t, easeOutQuad: t => t * (2 - t), easeInOutQuad: t => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t, easeInCubic: t => t * t * t, easeOutCubic: t => --t * t * t + 1, easeInOutCubic: t => t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1, easeInQuart: t => t * t * t * t, easeOutQuart: t => 1 - --t * t * t * t, easeInOutQuart: t => t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t, easeInSine: t => 1 - Math.cos(t * Math.PI / 2), easeOutSine: t => Math.sin(t * Math.PI / 2), easeInOutSine: t => -(Math.cos(Math.PI * t) - 1) / 2, easeInExpo: t => t === 0 ? 0 : Math.pow(2, 10 * t - 10), easeOutExpo: t => t === 1 ? 1 : 1 - Math.pow(2, -10 * t), easeInOutExpo: t => { if (t === 0) return 0; if (t === 1) return 1; return t < 0.5 ? Math.pow(2, 20 * t - 10) / 2 : (2 - Math.pow(2, -20 * t + 10)) / 2; }, easeInCirc: t => 1 - Math.sqrt(1 - Math.pow(t, 2)), easeOutCirc: t => Math.sqrt(1 - Math.pow(t - 1, 2)), easeInOutCirc: t => { return t < 0.5 ? (1 - Math.sqrt(1 - Math.pow(2 * t, 2))) / 2 : (Math.sqrt(1 - Math.pow(-2 * t + 2, 2)) + 1) / 2; }, easeInBack: t => { const c1 = 1.70158; const c3 = c1 + 1; return c3 * t * t * t - c1 * t * t; }, easeOutBack: t => { const c1 = 1.70158; const c3 = c1 + 1; return 1 + c3 * Math.pow(t - 1, 3) + c1 * Math.pow(t - 1, 2); }, easeInOutBack: t => { const c1 = 1.70158; const c2 = c1 * 1.525; return t < 0.5 ? Math.pow(2 * t, 2) * ((c2 + 1) * 2 * t - c2) / 2 : (Math.pow(2 * t - 2, 2) * ((c2 + 1) * (t * 2 - 2) + c2) + 2) / 2; }, easeOutBounce: t => { const n1 = 7.5625; const d1 = 2.75; if (t < 1 / d1) { return n1 * t * t; } else if (t < 2 / d1) { return n1 * (t -= 1.5 / d1) * t + 0.75; } else if (t < 2.5 / d1) { return n1 * (t -= 2.25 / d1) * t + 0.9375; } else { return n1 * (t -= 2.625 / d1) * t + 0.984375; } }, easeInBounce: t => 1 - easingFunctions.easeOutBounce(1 - t), easeInOutBounce: t => t < 0.5 ? (1 - easingFunctions.easeOutBounce(1 - 2 * t)) / 2 : (1 + easingFunctions.easeOutBounce(2 * t - 1)) / 2 }; // Animation utilities class ChartAnimationUtils { static createKeyframeSequence(from, to, steps = 10, easing = 'easeOutQuad') { const keyframes = []; const easeFn = easingFunctions[easing]; for (let i = 0; i <= steps; i++) { const progress = i / steps; const easedProgress = easeFn(progress); const value = from + (to - from) * easedProgress; keyframes.push({ progress, value, easing: easeFn }); } return keyframes; } static interpolateValue(from, to, progress, easing = 'linear') { const easeFn = easingFunctions[easing]; const easedProgress = easeFn(progress); return from + (to - from) * easedProgress; } static animateDataPoints(dataPoints, targetValues, progress, easing = 'easeOutQuad') { return dataPoints.map((point, index) => { const targetValue = targetValues[index]; if (targetValue === undefined || typeof point.y !== 'number') { return point; } const animatedValue = this.interpolateValue(point.y, targetValue, progress, easing); return { ...point, y: animatedValue }; }); } static animateSeries(series, targetSeries, progress, easing = 'easeOutQuad', staggerDelay = 0) { return series.map((seriesItem, seriesIndex) => { const targetSeriesItem = targetSeries[seriesIndex]; if (!targetSeriesItem) return seriesItem; const seriesProgress = Math.max(0, Math.min(1, progress - staggerDelay * seriesIndex / 1000)); const animatedData = this.animateDataPoints(seriesItem.data, targetSeriesItem.data.map(p => typeof p.y === 'number' ? p.y : 0), seriesProgress, easing); return { ...seriesItem, data: animatedData }; }); } static createSequence(keyframes, duration, delay = 0, repeat = false, yoyo = false) { return { keyframes, duration, delay, repeat, yoyo }; } static getValueAtProgress(sequence, progress) { if (sequence.keyframes.length === 0) return 0; if (sequence.keyframes.length === 1) return sequence.keyframes[0].value; // Find the appropriate keyframe pair for (let i = 0; i < sequence.keyframes.length - 1; i++) { const current = sequence.keyframes[i]; const next = sequence.keyframes[i + 1]; if (progress >= current.progress && progress <= next.progress) { const localProgress = (progress - current.progress) / (next.progress - current.progress); const easedProgress = next.easing ? next.easing(localProgress) : localProgress; return current.value + (next.value - current.value) * easedProgress; } } // Return last keyframe value if progress is beyond the sequence return sequence.keyframes[sequence.keyframes.length - 1].value; } static createSpringAnimation(from, to, config = {}) { const { stiffness = 100, damping = 10, mass = 1 } = config; // Generate keyframes based on spring physics const keyframes = []; const steps = 60; // 60fps for smooth animation const dt = 1 / steps; let position = from; let velocity = 0; let time = 0; const maxTime = 2; // Maximum animation time in seconds while (time < maxTime) { const displacement = to - position; const springForce = displacement * stiffness; const dampingForce = -velocity * damping; const acceleration = (springForce + dampingForce) / mass; velocity += acceleration * dt; position += velocity * dt; const progress = Math.min(time / maxTime, 1); keyframes.push({ progress, value: position, easing: easingFunctions.easeOutQuad }); // Stop if we're close enough to target and velocity is low if (Math.abs(displacement) < 0.01 && Math.abs(velocity) < 0.01) { break; } time += dt; } // Ensure we end at the target value keyframes.push({ progress: 1, value: to, easing: easingFunctions.easeOutQuad }); return { keyframes, duration: time * 1000, delay: 0, repeat: false, yoyo: false }; } static createMorphingAnimation(fromShape, toShape, config = {}) { const { steps = 20, easing = 'easeInOutQuad' } = config; const keyframes = []; for (let i = 0; i <= steps; i++) { const progress = i / steps; const easedProgress = easingFunctions[easing](progress); keyframes.push({ progress, value: easedProgress, easing: easingFunctions[easing] }); } return { keyframes, duration: 1000, delay: 0, repeat: false, yoyo: false }; } } // Utility functions for common animation patterns const createFadeInAnimation = (duration = 500, delay = 0) => { return ChartAnimationUtils.createSequence(ChartAnimationUtils.createKeyframeSequence(0, 1, 10, 'easeOutQuad'), duration, delay, false, false); }; const createSlideInAnimation = (direction = 'up', distance = 50, duration = 500, delay = 0) => { return ChartAnimationUtils.createSequence(ChartAnimationUtils.createKeyframeSequence(0, 1, 10, 'easeOutQuad'), duration, delay, false, false); }; const createScaleInAnimation = (from = 0, to = 1, duration = 500, delay = 0) => { return ChartAnimationUtils.createSequence(ChartAnimationUtils.createKeyframeSequence(from, to, 10, 'easeOutBack'), duration, delay, false, false); }; const createBounceAnimation = (amplitude = 20, duration = 1000, delay = 0) => { const keyframes = [{ progress: 0, value: 0, easing: easingFunctions.easeOutQuad }, { progress: 0.2, value: -amplitude * 0.6, easing: easingFunctions.easeOutQuad }, { progress: 0.4, value: amplitude * 0.4, easing: easingFunctions.easeOutQuad }, { progress: 0.6, value: -amplitude * 0.2, easing: easingFunctions.easeOutQuad }, { progress: 0.8, value: amplitude * 0.1, easing: easingFunctions.easeOutQuad }, { progress: 1, value: 0, easing: easingFunctions.easeOutQuad }]; return ChartAnimationUtils.createSequence(keyframes, duration, delay, false, false); }; // Utility functions for common animation patterns const calculateDamping = (dampingRatio, stiffness, mass) => { return 2 * Math.sqrt(mass * stiffness) * dampingRatio; }; const createAnimationOptions = (config = {}) => { const { duration = 1000, easing = 'easeOutQuad', delay = 0 } = config; return { duration, easing: easingFunctions[easing] || easingFunctions.easeOutQuad, delay, fill: 'both' }; }; const pathAnimationPlugin = { id: 'pathAnimation', beforeInit: chart => { chart.pathAnimation = { progress: 0, duration: 1000, startTime: 0, animating: false }; }, beforeDraw: (chart, args, options) => { chart.ctx; const pathAnim = chart.pathAnimation; if (!pathAnim.animating) return; const elapsed = Date.now() - pathAnim.startTime; const progress = Math.min(elapsed / pathAnim.duration, 1); // Update progress pathAnim.progress = progress; // Apply path animation to line datasets chart.data.datasets.forEach((dataset, datasetIndex) => { const meta = chart.getDatasetMeta(datasetIndex); if (meta.type === 'line' && meta.data) { meta.data.forEach((element, index) => { if (index / meta.data.length <= progress) { element._view = element._model; } else { // Hide elements that haven't been drawn yet element._view = { ...element._model, skip: true }; } }); } }); // Complete animation when done if (progress >= 1) { pathAnim.animating = false; chart.update('none'); } }, // Utility method to start path animation startAnimation: (chart, duration = 1000) => { if (chart.pathAnimation) { chart.pathAnimation.startTime = Date.now(); chart.pathAnimation.duration = duration; chart.pathAnimation.animating = true; chart.pathAnimation.progress = 0; } } }; // Additional utility functions const createEntranceAnimation = (series, type = 'fadeIn', config = {}, onUpdate, onComplete) => { const { duration = 1000, delay = 0, stagger = 100 } = config; return { duration, delay, stagger, easing: 'easeOutCubic', onUpdate, onComplete }; }; export { ChartAnimationUtils, calculateDamping, createAnimationOptions, createBounceAnimation, createEntranceAnimation, createFadeInAnimation, createScaleInAnimation, createSlideInAnimation, easingFunctions, pathAnimationPlugin }; //# sourceMappingURL=ChartAnimationUtils.js.map