ticker.dart 1.98 KB
Newer Older
1 2 3 4 5 6
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';

7
import 'scheduler.dart';
8

Adam Barth's avatar
Adam Barth committed
9
typedef TickerCallback(Duration elapsed);
10 11

/// Calls its callback once per animation frame
12
class Ticker {
13
  /// Constructs a ticker that will call onTick once per frame while running
Adam Barth's avatar
Adam Barth committed
14
  Ticker(TickerCallback onTick) : _onTick = onTick;
15

Adam Barth's avatar
Adam Barth committed
16
  final TickerCallback _onTick;
17 18 19

  Completer _completer;
  int _animationId;
20
  Duration _startTime;
21

22 23 24
  /// Start calling onTick once per animation frame
  ///
  /// The returned future resolves once the ticker stops ticking.
25 26
  Future start() {
    assert(!isTicking);
27
    assert(_startTime == null);
28 29 30 31 32
    _completer = new Completer();
    _scheduleTick();
    return _completer.future;
  }

33 34 35
  /// Stop calling onTick
  ///
  /// Causes the future returned by [start] to resolve.
36 37 38 39
  void stop() {
    if (!isTicking)
      return;

40 41
    _startTime = null;

42 43 44 45 46
    if (_animationId != null) {
      scheduler.cancelAnimationFrame(_animationId);
      _animationId = null;
    }

Adam Barth's avatar
Adam Barth committed
47
    // We take the _completer into a local variable so that isTicking is false
48 49
    // when we actually complete the future (isTicking uses _completer
    // to determine its state).
50 51 52 53 54 55
    Completer localCompleter = _completer;
    _completer = null;
    assert(!isTicking);
    localCompleter.complete();
  }

56
  /// Whether this ticker has scheduled a call to onTick
57 58
  bool get isTicking => _completer != null;

59
  void _tick(Duration timeStamp) {
60 61 62 63
    assert(isTicking);
    assert(_animationId != null);
    _animationId = null;

64 65 66 67
    if (_startTime == null)
      _startTime = timeStamp;

    _onTick(timeStamp - _startTime);
68

69 70
    // The onTick callback may have scheduled another tick already.
    if (isTicking && _animationId == null)
71 72 73 74 75 76 77 78 79
      _scheduleTick();
  }

  void _scheduleTick() {
    assert(isTicking);
    assert(_animationId == null);
    _animationId = scheduler.requestAnimationFrame(_tick);
  }
}