mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Pipe the remaining time for an animation all the way out to the AnimatedValue. Make splashes abortable, which causes them to continue to fade but no longer grow, by having them fade in 100ms or however long the animation was still going to go for, whichever is quickest. Make Scrollables support objects registering with them to be told when scrolling happens. Make UINode support subclasses being informed when _remove() was called. Hook all that together to make splashes go away when scrolling by having them register with any ancestor Scrollables such that when those scroll, all the splashes get aborted. Unregister when removed. R=eseidel@chromium.org Review URL: https://codereview.chromium.org/1092423003
162 lines
3.5 KiB
Dart
162 lines
3.5 KiB
Dart
// 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;
|
|
import 'mechanics.dart';
|
|
|
|
abstract class Generator {
|
|
Stream<double> get onTick;
|
|
void cancel();
|
|
}
|
|
|
|
class FrameGenerator extends Generator {
|
|
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 Generator {
|
|
Stream<double> get onTick => _stream;
|
|
final double initialDelay;
|
|
final double duration;
|
|
final double begin;
|
|
final double end;
|
|
final Curve curve;
|
|
|
|
FrameGenerator _generator;
|
|
Stream<double> _stream;
|
|
bool _done = false;
|
|
double _lastTime;
|
|
|
|
AnimationGenerator({
|
|
this.initialDelay: 0.0,
|
|
this.duration,
|
|
this.begin: 0.0,
|
|
this.end: 1.0,
|
|
this.curve: linear,
|
|
Function onDone
|
|
}) {
|
|
assert(curve != null);
|
|
assert(duration != null && duration > 0.0);
|
|
_generator = new FrameGenerator(onDone: onDone);
|
|
|
|
double startTime = 0.0;
|
|
_stream = _generator.onTick.map((timeStamp) {
|
|
if (startTime == 0.0)
|
|
startTime = timeStamp;
|
|
|
|
double t = (timeStamp - (startTime + initialDelay)) / duration;
|
|
_lastTime = math.max(0.0, math.min(t, 1.0));
|
|
return _lastTime;
|
|
})
|
|
.takeWhile(_checkForCompletion)
|
|
.where((t) => t >= 0.0)
|
|
.map(_transform);
|
|
}
|
|
|
|
double get remainingTime {
|
|
if (_lastTime == null)
|
|
return duration;
|
|
return duration - _lastTime;
|
|
}
|
|
|
|
void cancel() {
|
|
_generator.cancel();
|
|
}
|
|
|
|
double _transform(double t) {
|
|
if (_done)
|
|
return end;
|
|
return begin + (end - begin) * curve.transform(t);
|
|
}
|
|
|
|
// This is required because Dart Streams don't have takeUntil (inclusive).
|
|
bool _checkForCompletion(double t) {
|
|
if (_done)
|
|
return false;
|
|
|
|
_done = t >= 1;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
class Simulation extends Generator {
|
|
Stream<double> get onTick => _stream;
|
|
final System system;
|
|
|
|
FrameGenerator _generator;
|
|
Stream<double> _stream;
|
|
double _previousTime = 0.0;
|
|
|
|
Simulation(this.system, {Function terminationCondition, Function onDone}) {
|
|
_generator = new FrameGenerator(onDone: onDone);
|
|
_stream = _generator.onTick.map(_update);
|
|
|
|
if (terminationCondition != null) {
|
|
bool done = false;
|
|
_stream = _stream.takeWhile((_) {
|
|
if (done)
|
|
return false;
|
|
done = terminationCondition();
|
|
return true;
|
|
});
|
|
}
|
|
}
|
|
|
|
void cancel() {
|
|
_generator.cancel();
|
|
}
|
|
|
|
double _update(double timeStamp) {
|
|
double previousTime = _previousTime;
|
|
_previousTime = timeStamp;
|
|
if (previousTime == 0.0)
|
|
return timeStamp;
|
|
double deltaT = timeStamp - previousTime;
|
|
system.update(deltaT);
|
|
return timeStamp;
|
|
}
|
|
}
|