/
tween.dart
205 lines (159 loc) · 6.02 KB
/
tween.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
part of '../animation.dart';
/// Use the [Tween] class to animate the properties of a display object like
/// x, y, scaleX, scaleY, alpha, rotation etc. The animation starts with the
/// current value of the property and ends at a given target or delta value.
///
/// Use one of the predefined [Transition] functions to control the progress
/// of the animation (linear, easeInQuadratic, easeInCubic, ...). If none of
/// the predefined [Transition] functions fulfills your needs you can also
/// define your own function (see [TransitionFunction]).
///
/// Examples:
///
/// var tween = new Tween(mySprite, 1.0, Transition.easeInCubic);
/// tween.delay = 0.5;
/// tween.animate.alpha.to(0.0); // target value = 0.0
/// tween.animate.x.by(10.0); // delta value = 10.0;
/// tween.animate.y.by(-10.0); // delta value = -10.0;
/// tween.onComplete = () => print('completed');
/// stage.juggler.add(tween);
///
/// var sawtooth = Tween(mySprite, 1.0, (r) => (r * 4).remainder(1.0);
/// sawtooth.animate.y.to(10);
/// stage.juggler.add(sawtooth);
///
/// stage.juggler.addTween(mySprite, 1.0, Transition.easeInCubic)
/// ..delay = 0.5
/// ..animate.alpha.to(0.0);
class Tween implements Animatable {
final TweenObject _tweenObject;
final TransitionFunction _transition;
final List<TweenProperty> _tweenPropertyList = <TweenProperty>[];
void Function()? _onStart;
void Function()? _onUpdate;
void Function()? _onComplete;
num _totalTime = 0.0;
num _currentTime = 0.0;
num _delay = 0.0;
/// Specifies if the values should be rounded to an integer.
///
/// Default is false.
bool roundToInt = false;
bool _started = false;
/// Creates a new [Tween] for the specified [TweenObject] with a duration
/// of [time] seconds.
///
/// All display objects implements [TweenObject2D] and all 3D display
/// additionally objects implements [TweenObject3D]. Therefore all
/// display objects can be used with with tweens.
Tween(TweenObject tweenObject, num time,
[TransitionFunction transition = Transition.linear])
: _tweenObject = tweenObject,
_transition = transition {
_totalTime = max(0.0001, time);
}
//---------------------------------------------------------------------------
/// Accessor for 2D properties like x, y, rotation, alpha and others which
/// can be animated with this tween. Works for all display objects.
TweenPropertyAccessor2D get animate {
final tweenObject = _tweenObject;
if (tweenObject is TweenObject2D) {
return TweenPropertyAccessor2D._(this, tweenObject);
} else {
throw StateError('Invalid tween object for 2D animation.');
}
}
/// Accessor for 3D properties like offsetZ, rotationZ and others which
/// can be animated with this tween. Works for all 3D display objects.
TweenPropertyAccessor3D get animate3D {
final tweenObject = _tweenObject;
if (tweenObject is TweenObject3D) {
return TweenPropertyAccessor3D._(this, tweenObject);
} else {
throw StateError('Invalid tween object for 3D animation.');
}
}
TweenProperty _createTweenProperty(
TweenPropertyAccessor accessor, int propertyID) {
final tweenProperty = TweenProperty._(accessor, propertyID);
if (_started == false) _tweenPropertyList.add(tweenProperty);
return tweenProperty;
}
//---------------------------------------------------------------------------
@override
bool advanceTime(num time) {
if (_currentTime < _totalTime || _started == false) {
_currentTime = _currentTime + time;
if (_currentTime > _totalTime) {
_currentTime = _totalTime;
}
if (_currentTime >= 0.0) {
// set startValues if this is the first start
if (_started == false) {
_started = true;
for (var i = 0; i < _tweenPropertyList.length; i++) {
_tweenPropertyList[i]._init();
}
if (_onStart != null) {
_onStart!();
}
}
// calculate transition ratio and value
final num ratio = _currentTime / _totalTime;
final num transition = _transition(ratio).toDouble();
for (var i = 0; i < _tweenPropertyList.length; i++) {
_tweenPropertyList[i]._update(transition, roundToInt);
}
if (_onUpdate != null) {
_onUpdate!();
}
if (_onComplete != null && _currentTime == _totalTime) {
_onComplete!();
}
}
}
return _currentTime < _totalTime;
}
//---------------------------------------------------------------------------
/// Advances this [Tween] to its end state.
void complete() {
if (_totalTime >= _currentTime) {
advanceTime(_totalTime - _currentTime);
}
}
//---------------------------------------------------------------------------
/// The object that is tweened.
TweenObject get tweenObject => _tweenObject;
/// The total time of this [Tween].
num get totalTime => _totalTime;
/// The current time of this [Tween].
num get currentTime => _currentTime;
/// The delay this [Tween] waits until it starts animating.
///
/// The delay may be changed as long as the animation has not been started.
num get delay => _delay;
set delay(num value) {
if (_started == false) {
_currentTime = _currentTime + _delay - value;
_delay = value;
}
}
/// Indicates if this [Tween] is completed.
bool get isComplete => _currentTime >= _totalTime;
//---------------------------------------------------------------------------
/// The function that is called when this [Tween] starts.
///
/// This happens after the specified [delay].
set onStart(void Function() function) {
_onStart = function;
}
/// The function that is called every time this [Tween] updates the
/// properties of the [TweenObject].
set onUpdate(void Function() function) {
_onUpdate = function;
}
/// The function that is called when this [Tween] is completed.
set onComplete(void Function() function) {
_onComplete = function;
}
}