Question

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));
}
Was it helpful?

Solution

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.
  • You should add your action to mt.move(p).then((v) => doThisAfterTransitionEnd);
  • I tried your code and 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)); 
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top