Would it be out-of-scope to provide a Promise for animation completion? Something like Web Animations finished Promise:
var myAnimation = anime({
targets: ['.blue', '.green'],
translateX: '13rem',
rotate: 180,
borderRadius: 8,
duration: 2000,
loop: true
});
myAnimation.finished.then(() => {
/* ... */
});
Since loop: true indicates a Promise that never really ends, this might be too complex to simply tack on. I think Web Animations re-assign the finished property, which seems rather ugly for this.
Maybe something like this (inspired by jQuery) could work:
var myAnimation = anime({
targets: ['.blue', '.green'],
translateX: '13rem',
rotate: 180,
borderRadius: 8,
duration: 2000,
loop: true
});
// Wait for the current Promise to complete. Is called recursively
// upon the prior loop's completion.
function animationCompleted() {
return myAnimation.promise().then(() => {
console.log('Animation loop finished');
return animationCompleted();
});
}
// Kick off infinite-Promise resolution.
animationCompleted();
The promise() invocation would infer a new Promise that will resolve when the current animation completes. If loop: false is set, then the same Promise would be returned.
Perhaps I'm understanding you incorrectly, but wouldn't you require a callback? A promise would imply that you want to asynchronously run an animation, whereas really you're looking for when the animation is completed, thus a finished callback would be more appropriate.
Actually callback is also called asynchronously but immediately after animation is finished. And promise callback would be placed into execution queue.
Ah, I see. I did misunderstand. I assume, you're looking to chain animations
:+1:
I like the idea, and wanted to add promise initially, but I never really had the need to use it at this point.
But it's on my list.
@juliangarnier This issue was opened to get your blessing for a PR. If I implement it will you consider?
It is very useful when you have separate animations that have to be put into a sequence. @tbranyen I'd like to contribute.
@tbranyen Yes I will!
I just created a branch for all the new developments that will potentially be released in v1.1.
Please PR here from now https://github.com/juliangarnier/anime/tree/v1.1
Thanks
Cool @juliangarnier hoping to tackle this after work today, I'll keep you posted.
I just created a branch for all the new developments that will potentially be released in v1.1.
Please PR here from now https://github.com/juliangarnier/anime/tree/v1.1Thanks
@juliangarnier cool 馃憤
@tbranyen If you implement this issue, please let me know.
We seem to be better when implemented in parallel.
This is my PR #23
There is a new Proposed syntax for promise based animation event detection in the latest branches of anime @juliangarnier has implemented some in a branch of his and I have implemented a non blocking event system based version with the same syntax on my fork .
The proposed syntax looks like this
var i = 0;
myAnimation.on('update', function(anim) {
console.log('update step :',i++); // 1,2,3,4,5...
});
myAnimation.once('complete').then(function(anim) {
console.log('completed once');
anim.play(); // will re-play the animation only once
});
// basic layout for reacting on an event
animation.on( eventname , callback);
animation.once( eventname ) // -> promise
:-1: Sorry that looks very confusing. I see events, callbacks, and Promises control flow all rolled into the exact same API.
Why was the promise() method not sufficient? What does this new API solve?
.promise() leaves out room for different events.
Do you have a better proposed syntax , I suggest perhaps adding
animation.complete.then( func ):
animation.begin.then( func );
animation.pause.then( func );
I see, the goal of the Promise is to represent an animation transaction, it is not used for general events. My recommendation would be to separate the two entirely.
You have an event based system to hook into the animation states. And a very simple Promise API to know when the animation completes. If loop: true is set, then calling promise() again gets a new Promise since a new animation has started.
.promise() solely for when the animation finishes is a bit confusing.
// I think then that this promise getter is simpler than .promise()
// it has more symantic value than .promise() as the user knows what the promise
// is for
animation.complete // -> promise
anime-next implements the following
// .once always returns a promise
myAnimation.once('begin').then(anim => {
console.log("Began!"); // Called the animation began.
});
// but you can also use
myAnimation.begin.then(anim => {
console.log("Began!"); // Called the animation began.
});
// or
myAnimation.begin = anim => {
console.log("Began!"); // Called the animation began.
};
// and for events that get called more than once
myAnimation.on('begin', anim => {
console.log("Began!"); // Called the animation began.
});
I'm afraid I disagree, providing events like update with a Promise is confusing (since Promise resolution is immutable once set). If you ignore that event, the API becomes inconsistent, which is less than ideal... With the API you have above I can't tell if the begin callback can get called multiple times, while the promise only gets resolved for the first. Can you tell just by looking at it?
It makes significantly more sense to model the Promise after the animation transaction. They are parallels in concept and implementation. With the suggestion you've made to use complete there would be no way to hook into various completes with loop: true, right?
You're not meant to use update with a promise you can if you have to but it will run once as you say. That is why .on is provided promises in the case of the anime-next fork is optional you can do all the things with out it, promises give those who want to use them choice , benefits and all the problems that come with them. In anime-next I implemented an interloop event since complete would not be viable it would be better if instead you could react to when a loop ends and starts
I've built a promise based animation class. Works really well. Currently I've only got it working with "tweens" not looping animations but I'm working on it. I'm using it with threejs so not for DOM manipulations which is where something like anime is probably better suited.
Anyway the basic premise is that you start the animation and return a promise from that method, then resolve the promise with an end method. In my class the end method is private. There's a public stop method that can be called which also returns the promise then calls end.
Anyway it's really useful for chaining, a little cleaner than callback chains in the complete prop. Would be really cool to see anime support promises. It's such a nice way of animating, makes it easy to do things like
animationA.start().then(function () {
return animationB.start();
}).then(function () {
return animationC.start();
}).then(function () {
console.log('A, B & C are done');
});
Okay so here we go, I built a _very quick_ (ie., on the bus to work in 10 minutes!) Promise wrapper for animejs http://codepen.io/rohandeshpande/pen/PzJdkz
It uses Bluebird and Promise.defer() but if that bothers you then it's easy to change I think.
Edit right now this won't support looped animations but perhaps for the looped mode you can resolve the promise in a setTimeout inside the begin method... that's kind of ugly but I'll try it out.
I think the best way would be for loop to use an internal promise chain and then you can return the promise from the first resolved promise in that chain.
Implementation here:
https://github.com/juliangarnier/anime/pull/106#issuecomment-276546443
AND merged to v2.
Most helpful comment
Maybe something like this (inspired by jQuery) could work:
The
promise()invocation would infer a new Promise that will resolve when the current animation completes. Ifloop: falseis set, then the same Promise would be returned.