I'am trying to program some animations but I am having troubles to understand how the Futures work on Dart.
The main problem is that the animation itself is an asynchronous process and, if I try to chain several points, they pile up and the sprite moves directly to the last point. All the examples I've seen work when the function returns a value but this is not the case when dealing with animations.
I'd like to be able to detect then the animation is finished, in order to trigger the next movement, but I've not been really successful so far.
Here is my code:
class MovingThing {
String name;
DivElement sprite = new DivElement();
MovingThing(this.name){
sprite.id = name;
sprite.text = name;
sprite.style..width = "30px"
..height = "30px"
..border = "1px solid black"
..position = "absolute"
..transition = "all 2000ms ease-in-out";
querySelector("body").children.add(sprite);
}
Future move(Point p) {
sprite.style..top = p.y.toString() + "px"
..left = p.x.toString() + "px";
return Future.wait([sprite.onTransitionEnd.first]);
}
}
main () {
List<Point> points = [
new Point(20, 20)
, new Point(200, 20)
, new Point(20, 200)
, new Point(100, 100)
];
MovingThing mt = new MovingThing("MT");
Future.forEach(points, (Point p) => mt.move(p));
}
I several things
Future.wait()
does return immediately not when onTransitionEnd
is fired.Future.wait
is for waiting for more than one Future
hence the List parameter.
you could use return sprite.onTransitionEnd.first;
instead this line.mt.move(p).then((v) => doThisAfterTransitionEnd);
onTransitionEnd
was not fired.not perfect but should you show how to start.
new Future()
is only used to give the event loop time to do it's work not to chain the animations.
The next iteration of the animation starts with the onSubscriptionEnd
event.
import 'dart:html';
import 'dart:async';
class MovingThing {
String name;
DivElement sprite = new DivElement();
List<Point> points;
MovingThing(this.name){
sprite.id = name;
sprite.text = name;
sprite.style
..top = "30px"
..left = "30px"
..width = "30px"
..height = "30px"
..border = "1px solid black"
..position = "absolute"
..transition = "all 1.5s ease-in-out";
document.body.children.add(sprite);
}
void move(int idx) {
if(idx >= points.length) {
return;
} else {
var f = sprite.onTransitionEnd.first.then((TransitionEvent e) {
new Future(() {
print('transitionEnd$idx');
move(idx + 1);
});
});
sprite.style
..top = '${points[idx].x}px'
..left = '${points[idx].y}px';
sprite.text = '$idx';
}
}
}
main () {
List<Point> points = [
new Point(120, 120)
, new Point(200, 20)
, new Point(20, 200)
, new Point(100, 100)
, new Point(150, 30)
, new Point(30, 150)
, new Point(20, 20)
, new Point(120, 120)
];
MovingThing mt = new MovingThing("MT");
mt.points = points;
new Future(() => mt.move(0));
}