@omicrxn/mercury
Version:
Mercury is a Svelte animation library using AnimeJS under the hood. It simplifies complex animations with Svelte actions, provides layout and exit animations, and integrates seamlessly with Svelte features.
96 lines (95 loc) • 3.41 kB
JavaScript
import { mapTransitionToAnimeJS } from '../utils.js';
let animeModule = null;
let loadPromise = null;
async function loadAnime() {
if (animeModule)
return animeModule;
if (typeof window !== 'undefined' && window.anime) {
animeModule = window.anime;
return animeModule;
}
if (!loadPromise) {
loadPromise = import('animejs').then((mod) => {
animeModule = mod.default ?? mod;
return animeModule;
}, () => {
throw new Error('Please install AnimeJS: npm install animejs');
});
}
return loadPromise;
}
export const AnimeEngine = {
animate(element, params) {
const { animate: mercuryAnimation, transition: mercuryTransition, callbacks } = params;
let animation = null;
let animeReady = false;
let pendingOperations = [];
// Load AnimeJS in background
loadAnime().then(anime => {
animeReady = true;
//Mapping animation to motion
const animationOptions = mercuryAnimation;
//Mapping transition to motion
const transitionOptions = mapTransitionToAnimeJS(mercuryTransition, callbacks);
transitionOptions.ease =
mercuryTransition?.type === 'spring'
? anime.createSpring({
stiffness: mercuryTransition?.stiffness,
damping: mercuryTransition?.damping,
mass: mercuryTransition?.mass,
velocity: mercuryTransition?.velocity
})
: mercuryTransition?.ease;
animation = anime.animate(element, { ...animationOptions, ...transitionOptions });
// Execute queued operations
pendingOperations.forEach(op => op());
pendingOperations = [];
}).catch(error => {
console.error('Failed to load AnimeJS:', error);
});
const instance = {
completed: false,
play: () => {
if (animeReady && animation) {
animation.restart();
}
else {
pendingOperations.push(() => animation?.restart());
}
},
pause: () => {
if (animeReady && animation) {
animation.pause();
}
else {
pendingOperations.push(() => animation?.pause());
}
},
cancel: () => {
if (animeReady && animation) {
animation.cancel();
}
else {
pendingOperations.push(() => animation?.cancel());
}
},
onComplete: (onResolve) => {
if (animeReady && animation) {
return animation.then(() => {
onResolve();
instance.completed = true;
});
}
else {
pendingOperations.push(() => {
animation?.then(() => {
onResolve();
instance.completed = true;
});
});
}
}
};
return instance;
}
};