Is there any way to chain animations in anime.js or have queues / groups of animations that I can wait for in order to proceed with other animations?
Advertisement
Answer
Each animation with anime
returns a promise, so you can use async/await
in combination with Promise.all
, do remember, though, Promise.all
makes it so that all animations run concurrently. For example, let’s say you want 3 animations all to run at the same time, then, after that group is done, do another animation:
async function animateLockAndBackground() { const bigLockAnimation = anime({ targets: '#big-lock', strokeDashoffset: [0, 5], easing: 'easeInOutSine', duration: 250, easing: 'easeInSine' }).finished; const lockLineAnimation = anime({ targets: '#lock-line', strokeDashoffset: [0, 3], translateY: [{ value: '-2px', duration: 350, easing: 'easeOutExpo' }, { value: '2px', duration: 350, easing: 'easeOutExpo' }, { value: '-2px', duration: 350, easing: 'easeOutExpo' }, ], }).finished; const innerCircleAnimation = anime({ targets: '#inner-circle', translateY: [{ value: '-1px', duration: 250, easing: 'easeOutExpo' }, { value: '1px', duration: 250, easing: 'easeOutExpo' }, { value: '-1px', duration: 250, easing: 'easeOutExpo' }, { value: 0, duration: 250, easing: 'easeOutExpo' }, ], }).finished; await Promise.all([bigLockAnimation, lockLineAnimation, innerCircleAnimation]); } animateLockAndBackground().then(() => { console.log('First animation finished.'); anime({ targets: '.plugins-not-installed-text', translateY: [{ value: '10px', duration: 750 }] }); anime({ targets: '#lock-wrapper', translateY: [{ value: '-10px', duration: 750 }] }); anime({ targets: '#plugins-not-installed-screen', opacity: 0, duration: 500, easing: 'linear' }).finished.then(() => { console.log('Second animation finished.'); }); });
#plugins-not-installed-screen { display: flex; flex-direction: column; position: relative; width: 100%; } #plugins-not-installed-screen .upper { display: flex; justify-content: center; align-items: center; flex-direction: column; z-index: 2; padding: 24px 48px; background-image: url('../Images/component.png'); background-repeat: repeat; } .plugins-not-installed-text { font-size: 15px; text-align: center; } #lock { display: block; width: 50px; height: 65px; } #plugins-not-installed-screen #lock {} #plugins-not-installed-screen #big-lock { stroke-dasharray: 61 62; stroke-dashoffset: 5; /* go to 5 */ } #plugins-not-installed-screen #lock-line { stroke-dasharray: 31 33; stroke-dashoffset: 0; /* go to 3 */ } #components-to-install-list { display: flex; flex-direction: row; flex-wrap: wrap; width: 100%; } .install-component-individual { display: flex; flex-direction: row; justify-content: space-between; padding: 12px 0; border-bottom: 1px solid rgba(0, 0, 0, 0.1); width: 100%; }
<script src="https://cdn.jsdelivr.net/npm/animejs@3.1.0/lib/anime.min.js"></script> <div id="plugins-not-installed-screen" class=""> <div class="upper"> <div id="lock-wrapper"> <svg version="1.1" id="lock" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 25 35" style="enable-background:new 0 0 25 35;" xml:space="preserve"> <style type="text/css"> #big-lock{fill:none;stroke:#686868;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;} #inner-circle{fill:none;stroke:#686868;stroke-width:2;stroke-linecap:round;stroke-miterlimit:10;} #lock-line{fill:none;stroke:#686868;stroke-width:2;stroke-linecap:round;stroke-miterlimit:10;} </style> <path id="big-lock" d="M4.4,13.5c-1.2,0.8-2,2.1-2,3.6v4c0,2.8,1.1,5.4,3.1,7.4c1.9,1.9,4.5,2.9,7.2,2.9 c0.1,0,0.2,0,0.3,0c5.5-0.1,10-4.9,10-10.5v-3.8c0.1-1.8-0.9-3.3-2.4-4l-6.5-2.7c-0.8-0.3-1.8-0.4-2.6,0L10.1,11"/> <circle id="inner-circle" cx="12.7" cy="21.9" r="2.9"/> <path id="lock-line" d="M7.1,15.1V9.9c0-3.1,2.5-5.6,5.6-5.6h0c3.1,0,5.6,2.5,5.6,5.6v8"/> </svg> </div> <h5 class="plugins-not-installed-text">Plugins not installed.</h5> </div> </div>
What, then, if you want to, inside that function, have the lock-line
animate at the same time the 2 other elements are animating, so instead of 3 animation timelines, you only have 2? Here:
async function animateLockAndBackground() { const bigLockAnimation = anime({ targets: '#big-lock', strokeDashoffset: [0, 5], easing: 'easeInOutSine', duration: 250, easing: 'easeInSine' }).finished; const innerCircleAnimation = anime({ targets: '#inner-circle', translateY: [ {value: '-1px', duration: 250, easing: 'easeOutExpo'}, {value: '1px', duration: 250, easing: 'easeOutExpo'}, {value: '-1px', duration: 250, easing: 'easeOutExpo'}, {value: 0, duration: 250, easing: 'easeOutExpo'}, ], }).finished; await Promise.all([bigLockAnimation, innerCircleAnimation]); } animateLockAndBackground().then(() => { return anime({ targets: '#lock-line', strokeDashoffset: [0, 3], translateY: [ {value: '-2px', duration: 350, easing: 'easeOutExpo'}, {value: '2px', duration: 350, easing: 'easeOutExpo'}, {value: '-2px', duration: 350, easing: 'easeOutExpo'}, ], }).finished; }).then(() => { anime({ targets: '.plugins-not-installed-text', translateY: [ {value: '10px', duration: 750} ] }); anime({ targets: '#lock-wrapper', translateY: [ {value: '-10px', duration: 750} ] }); anime({ targets: '#plugins-not-installed-screen', opacity: 0, duration: 500, easing: 'linear' }); });
We moved that lock-line
animation outside of the original group, made it wait for the group, then whatever else comes after the lock-line
animates after.
You should think about an animation as a simple promise that you can chain.