ember-animation / ember-animated

Core animation primitives for Ember.
https://ember-animation.github.io/ember-animated/
MIT License
244 stars 90 forks source link

Simplify sprite "garbage collection" #13

Open nickschot opened 6 years ago

nickschot commented 6 years ago

I found the need for a "wait" motion like liquid-fire provides (i.e. for keeping certain elements on screen while another animation finishes).

Sample implementation:

//ember-animated/motions/wait.js
import Motion from 'ember-animated/motion';
import { wait as timeout } from 'ember-animated/concurrency-helpers';

export default function wait(sprite, opts) {
  return new Wait(sprite, opts).run();
}

export class Wait extends Motion {
  constructor(sprite, opts) {
    super(sprite, opts);
  }

  * animate() {
    yield timeout(this.duration);
  }
}

and use:

// some component.js
function * someTransition({ removedSprites }){
    removedSprites.forEach(sprite => {
      wait(sprite);
    });
}

This can of course also be done by yielding the wait/timeout directly in the transition's generator function, but then the duration would need to be provided there.

Let me know your thoughts.

ef4 commented 6 years ago

In a lot of scenarios you don't need this. But yes, there are probably some cases where you do.

We don't do any kind of cleanup or removal of sprites until the whole transition finishes. So if you're just trying to keep some removed sprites visible while animating something else, you don't need to do anything. But interruptions also cause the transition to finish. At that point, any removed sprites that weren't still animating get garbage collected. A wait motion would be useful for that situation.

I think I should probably just change the garbage collection rule to be less aggressive. Instead of "drop any removed sprites that weren't still actively animating" it can be "drop any removed sprites that are not visible".

The only downside of that change would be that if people have unboundedly long chains of transitions interrupting each other (like the "auto" button of the /#/each route in the dummy app), they will need to explicitly do something like sprite.hide() if they want to avoid a big pileup of old sprites. That seems OK, since that's a rarer situation.

nickschot commented 6 years ago

But interruptions also cause the transition to finish. At that point, any removed sprites that weren't still animating get garbage collected.

I think I am/was seeing exactly this. If no generator is returned by the rule it will not be removed at all, if a generator is returned which doesn't do a motion with said sprite it is immediately removed (with other animations happening at the same time).