blob: b24c46227dff4e88f9f8ec82c97aaa2a6b70b85e [file] [log] [blame]
// 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 'curves.dart';
import 'dart:async';
import 'dart:math' as math;
import 'dart:sky' as sky;
class FrameGenerator {
Function onDone;
StreamController _controller;
Stream<double> get onTick => _controller.stream;
int _animationId = 0;
bool _cancelled = false;
FrameGenerator({this.onDone}) {
_controller = new StreamController(
sync: true,
onListen: _scheduleTick,
onCancel: cancel);
}
void cancel() {
if (_cancelled) {
return;
}
if (_animationId != 0) {
sky.window.cancelAnimationFrame(_animationId);
}
_animationId = 0;
_cancelled = true;
if (onDone != null) {
onDone();
}
}
void _scheduleTick() {
assert(_animationId == 0);
_animationId = sky.window.requestAnimationFrame(_tick);
}
void _tick(double timeStamp) {
_animationId = 0;
_controller.add(timeStamp);
if (!_cancelled) {
_scheduleTick();
}
}
}
class AnimationGenerator extends FrameGenerator {
Stream<double> get onTick => _stream;
final double duration;
final double begin;
final double end;
final Curve curve;
Stream<double> _stream;
bool _done = false;
AnimationGenerator(this.duration, {
this.begin: 0.0,
this.end: 1.0,
this.curve: linear,
Function onDone
}):super(onDone: onDone) {
assert(duration > 0);
double startTime = 0.0;
_stream = super.onTick.map((timeStamp) {
if (startTime == 0.0)
startTime = timeStamp;
return math.min((timeStamp - startTime) / duration, 1.0);
})
.takeWhile(_checkForCompletion)
.map(_transform);
}
double _transform(double t) {
if (_done)
return end;
return begin + (end - begin) * curve.transform(t);
}
bool _checkForCompletion(double t) {
if (_done)
return false;
_done = t >= 1;
return true;
}
}