Skip to content

Commit 1718d39

Browse files
committed
Add some basic animations
1 parent 002a2bd commit 1718d39

File tree

6 files changed

+357
-4
lines changed

6 files changed

+357
-4
lines changed

lib/animated_config.dart

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
import 'package:flutter/material.dart';
2+
import 'animated_interpolation.dart';
3+
4+
class AnimatedConfig {
5+
AnimatedConfig({
6+
this.opacity = 1,
7+
this.scale = 1,
8+
this.translateX = 0,
9+
this.translateY = 0,
10+
this.skewX = 0,
11+
this.skewY = 0,
12+
this.rotateX = 0,
13+
this.rotateY = 0,
14+
});
15+
final double opacity;
16+
final double scale;
17+
final double translateX;
18+
final double translateY;
19+
final double skewX;
20+
final double skewY;
21+
final double rotateX;
22+
final double rotateY;
23+
}
24+
25+
enum AnimatedType { opacity, scale, translateX, translateY, skewX, skewY, rotateX, rotateY }
26+
27+
const Duration _kDefaultDuration = const Duration(seconds: 1);
28+
29+
class SmartAnimatedWidget extends StatefulWidget {
30+
SmartAnimatedWidget({
31+
Key key,
32+
this.from,
33+
this.to,
34+
this.configMap,
35+
this.child,
36+
this.curve,
37+
this.duration = _kDefaultDuration,
38+
this.autoPlay = false,
39+
}) : super(key: key);
40+
final AnimatedConfig from;
41+
final AnimatedConfig to;
42+
final Map<double, AnimatedConfig> configMap;
43+
final Widget child;
44+
final Curve curve;
45+
final Duration duration;
46+
final bool autoPlay;
47+
48+
@override
49+
SmartAnimatedWidgetState createState() => SmartAnimatedWidgetState();
50+
}
51+
52+
class SmartAnimatedWidgetState extends State<SmartAnimatedWidget> with SingleTickerProviderStateMixin<SmartAnimatedWidget> {
53+
AnimationController _controller;
54+
Animation<double> _animation;
55+
bool _animating = false; //是否正在动画
56+
57+
@override
58+
void initState() {
59+
// TODO: implement initState
60+
super.initState();
61+
_controller = AnimationController(vsync: this, duration: widget.duration);
62+
_animation = Tween<double>(begin: 0, end: 1).animate(_controller);
63+
if (widget.autoPlay == true) {
64+
_controller.forward();
65+
_animating = true;
66+
}
67+
_controller.addStatusListener((status) {
68+
if (status == AnimationStatus.completed) {
69+
_animating = false;
70+
}
71+
});
72+
}
73+
74+
animate({Duration duration}) {
75+
if (_animating == false) {
76+
_controller.reset();
77+
_controller.forward();
78+
_animating = true;
79+
}
80+
}
81+
82+
@override
83+
void dispose() {
84+
// TODO: implement dispose
85+
_controller?.dispose();
86+
super.dispose();
87+
}
88+
89+
@override
90+
Widget build(BuildContext context) {
91+
return AnimatedBuilder(
92+
animation: _animation,
93+
builder: (BuildContext context, Widget child) => this.buildWidget(child),
94+
child: widget.child,
95+
);
96+
}
97+
98+
Widget buildWidget(Widget _child) {
99+
InterpolationTween opacityTween;
100+
InterpolationTween scaleTween;
101+
InterpolationTween translateXTween;
102+
InterpolationTween translateYTween;
103+
InterpolationTween skewXTween;
104+
InterpolationTween skewYTween;
105+
InterpolationTween rotateXTween;
106+
InterpolationTween rotateYTween;
107+
List<double> inputRange = [0, 1];
108+
if (widget.from != null && widget.to != null) {
109+
AnimatedConfig fc = widget.from;
110+
AnimatedConfig tc = widget.to;
111+
scaleTween = InterpolationTween(inputRange: inputRange, outputRange: [fc.scale, tc.scale], curve: widget.curve);
112+
translateXTween = InterpolationTween(inputRange: inputRange, outputRange: [fc.translateX, tc.translateX], curve: widget.curve);
113+
translateYTween = InterpolationTween(inputRange: inputRange, outputRange: [fc.translateY, tc.translateY], curve: widget.curve);
114+
skewXTween = InterpolationTween(inputRange: inputRange, outputRange: [fc.skewX, tc.skewX], curve: widget.curve);
115+
skewYTween = InterpolationTween(inputRange: inputRange, outputRange: [fc.skewY, tc.skewY], curve: widget.curve);
116+
rotateXTween = InterpolationTween(inputRange: inputRange, outputRange: [fc.rotateX, tc.rotateX], curve: widget.curve);
117+
rotateYTween = InterpolationTween(inputRange: inputRange, outputRange: [fc.rotateY, tc.rotateY], curve: widget.curve);
118+
opacityTween = InterpolationTween(inputRange: inputRange, outputRange: [fc.opacity, tc.opacity], curve: widget.curve);
119+
}
120+
if (widget.configMap != null) {
121+
List<double> inputRange = [];
122+
List<double> scaleOutRange = [];
123+
List<double> translateXOutRange = [];
124+
List<double> translateYOutRange = [];
125+
List<double> skewXOutRange = [];
126+
List<double> skewYOutRange = [];
127+
List<double> rotateXOutRange = [];
128+
List<double> rotateYOutRange = [];
129+
List<double> opacityOutRange = [];
130+
List<double> keysList = widget.configMap.keys.toList();
131+
keysList.sort(); //从小到大排序
132+
for (int i = 0; i < keysList.length; i++) {
133+
double key = keysList.elementAt(i);
134+
inputRange.add(key);
135+
scaleOutRange.add(widget.configMap[key].scale);
136+
translateXOutRange.add(widget.configMap[key].translateX);
137+
translateYOutRange.add(widget.configMap[key].translateY);
138+
skewXOutRange.add(widget.configMap[key].skewX);
139+
skewYOutRange.add(widget.configMap[key].skewY);
140+
rotateXOutRange.add(widget.configMap[key].rotateX);
141+
rotateYOutRange.add(widget.configMap[key].rotateY);
142+
opacityOutRange.add(widget.configMap[key].opacity);
143+
}
144+
scaleTween = InterpolationTween(inputRange: inputRange, outputRange: scaleOutRange, curve: widget.curve);
145+
translateXTween = InterpolationTween(inputRange: inputRange, outputRange: translateXOutRange, curve: widget.curve);
146+
translateYTween = InterpolationTween(inputRange: inputRange, outputRange: translateYOutRange, curve: widget.curve);
147+
skewXTween = InterpolationTween(inputRange: inputRange, outputRange: skewXOutRange, curve: widget.curve);
148+
skewYTween = InterpolationTween(inputRange: inputRange, outputRange: skewYOutRange, curve: widget.curve);
149+
rotateXTween = InterpolationTween(inputRange: inputRange, outputRange: rotateXOutRange, curve: widget.curve);
150+
rotateYTween = InterpolationTween(inputRange: inputRange, outputRange: rotateYOutRange, curve: widget.curve);
151+
opacityTween = InterpolationTween(inputRange: inputRange, outputRange: opacityOutRange, curve: widget.curve);
152+
}
153+
154+
return Transform.scale(
155+
scale: scaleTween.evaluate(_animation),
156+
child: Transform.translate(
157+
offset: Offset(
158+
translateXTween.evaluate(_animation),
159+
translateYTween.evaluate(_animation),
160+
),
161+
child: Transform(
162+
transform: Matrix4.skew(
163+
skewXTween.evaluate(_animation),
164+
skewYTween.evaluate(_animation),
165+
),
166+
child: Transform(
167+
transform: Matrix4.rotationX(
168+
rotateXTween.evaluate(_animation),
169+
),
170+
child: Transform(
171+
transform: Matrix4.rotationY(
172+
rotateYTween.evaluate(_animation),
173+
),
174+
child: Opacity(
175+
opacity: opacityTween.evaluate(_animation),
176+
child: _child,
177+
),
178+
),
179+
),
180+
),
181+
),
182+
);
183+
}
184+
}

lib/animated_interpolation.dart

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import 'package:flutter/material.dart';
2-
2+
export 'fading.dart';
3+
export 'animated_config.dart';
4+
export 'bounce.dart';
5+
export 'sliding.dart';
6+
export 'zooming.dart';
37
///
48
/// 加强型的tween,可设置多个插值,受到React Native的插值动画启发
59
/// 和tween使用方法一样
@@ -120,8 +124,11 @@ class InterpolationConfigType {
120124
this.extrapolate,
121125
this.extrapolateLeft = ExtrapolateType.extend,
122126
this.extrapolateRight = ExtrapolateType.extend,
123-
}) : assert(inputRange.length >= 2),
124-
assert(outputRange.length >= 2);
127+
}) : assert(inputRange != null),
128+
assert(outputRange != null),
129+
assert(inputRange.length >= 2),
130+
assert(outputRange.length >= 2),
131+
assert(inputRange.length == outputRange.length);
125132

126133
final List<double> inputRange;
127134
final List<double> outputRange;
@@ -179,7 +186,7 @@ double interpolate({
179186
double inputMax,
180187
double outputMin,
181188
double outputMax,
182-
Curve curve,
189+
Curve curve = const _Linear._(),
183190
ExtrapolateType extrapolateLeft,
184191
ExtrapolateType extrapolateRight,
185192
}) {
@@ -227,6 +234,7 @@ double interpolate({
227234
}
228235

229236
// Easing
237+
if(curve == null)curve = _Linear._();
230238
result = curve.transform(result);
231239

232240
// Output Range

lib/bounce.dart

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import 'animated_config.dart';
2+
3+
Map<double, AnimatedConfig> bounceIn = {
4+
0: AnimatedConfig(opacity: 0, scale: 0.3),
5+
0.2: AnimatedConfig(scale: 1.1),
6+
0.4: AnimatedConfig(scale: 0.9),
7+
0.6: AnimatedConfig(opacity: 1, scale: 1.03),
8+
0.8: AnimatedConfig(scale: 0.97),
9+
1: AnimatedConfig(opacity: 1, scale: 1)
10+
};
11+
Map<double, AnimatedConfig> bounceInUp = {
12+
0: AnimatedConfig(opacity: 0, translateY: 800),
13+
0.6: AnimatedConfig(opacity: 1, translateY: -25),
14+
0.75: AnimatedConfig(translateY: 10),
15+
0.9: AnimatedConfig(translateY: -5),
16+
1: AnimatedConfig(translateY: 0)
17+
};
18+
Map<double, AnimatedConfig> bounceInDown = {
19+
0: AnimatedConfig(opacity: 0, translateY: -800),
20+
0.6: AnimatedConfig(opacity: 1, translateY: 25),
21+
0.75: AnimatedConfig(translateY: -10),
22+
0.9: AnimatedConfig(translateY: 5),
23+
1: AnimatedConfig(translateY: 0)
24+
};
25+
Map<double, AnimatedConfig> bounceInRight = {
26+
0: AnimatedConfig(opacity: 0, translateX: 600),
27+
0.6: AnimatedConfig(opacity: 1, translateX: -20),
28+
0.75: AnimatedConfig(translateX: -8),
29+
0.9: AnimatedConfig(translateX: -4),
30+
1: AnimatedConfig(translateY: 0)
31+
};
32+
Map<double, AnimatedConfig> bounceOut = {
33+
0: AnimatedConfig(),
34+
0.2: AnimatedConfig(scale: 0.9),
35+
0.5: AnimatedConfig(scale: 1.11),
36+
0.55: AnimatedConfig(scale: 1.11),
37+
1: AnimatedConfig(opacity: 0, scale: 0.3)
38+
};
39+
40+
Map<double, AnimatedConfig> bounceOutUp = {
41+
0: AnimatedConfig(),
42+
0.2: AnimatedConfig(translateY: -10),
43+
0.4: AnimatedConfig(translateY: 20),
44+
0.45: AnimatedConfig(translateY: 20),
45+
0.55: AnimatedConfig(),
46+
1: AnimatedConfig(opacity: 0, translateY: -800)
47+
};
48+
49+
Map bounceOutDown = {
50+
0: AnimatedConfig(),
51+
0.2: AnimatedConfig(translateY: 10),
52+
0.4: AnimatedConfig(translateY: -20),
53+
0.45: AnimatedConfig(translateY: -20),
54+
0.55: AnimatedConfig(opacity: 1),
55+
1: AnimatedConfig(opacity: 0, translateY: 800),
56+
};

lib/fading.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import 'animated_config.dart';
2+
3+
Map<double, AnimatedConfig> createFade(AnimatedType type, double fromValue) {
4+
return {
5+
0: AnimatedConfig(opacity: 0, translateX: type == AnimatedType.translateX ? fromValue : 0, translateY: type == AnimatedType.translateY ? fromValue : 0),
6+
1: AnimatedConfig(opacity: 1)
7+
};
8+
}
9+
10+
Map<double, AnimatedConfig> fadeInDown = createFade(AnimatedType.translateY, 100);
11+
Map<double, AnimatedConfig> fadeInUp = createFade(AnimatedType.translateY, -100);
12+
Map<double, AnimatedConfig> fadeInLeft = createFade(AnimatedType.translateX, -100);
13+
Map<double, AnimatedConfig> fadeInRight = createFade(AnimatedType.translateY, 100);
14+
Map<double, AnimatedConfig> fadeInDownBig = createFade(AnimatedType.translateY, 500);
15+
Map<double, AnimatedConfig> fadeInUpBig = createFade(AnimatedType.translateY, -500);
16+
Map<double, AnimatedConfig> fadeInLeftBig = createFade(AnimatedType.translateX, -500);
17+
Map<double, AnimatedConfig> fadeInRightBig = createFade(AnimatedType.translateY, 500);

lib/sliding.dart

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import 'animated_config.dart';
2+
3+
Map<double, AnimatedConfig> createSlide(AnimatedType type, double fromValue) {
4+
return {
5+
0: AnimatedConfig(translateX: type == AnimatedType.translateX ? fromValue : 0, translateY: type == AnimatedType.translateY ? fromValue : 0),
6+
1: AnimatedConfig()
7+
};
8+
}
9+
10+
Map<double, AnimatedConfig> createSlideOut(AnimatedType type, double fromValue) {
11+
return {
12+
0: AnimatedConfig(),
13+
1: AnimatedConfig(translateX: type == AnimatedType.translateX ? fromValue : 0, translateY: type == AnimatedType.translateY ? fromValue : 0),
14+
};
15+
}
16+
17+
Map<double, AnimatedConfig> slideOutDown = createSlideOut(AnimatedType.translateY, 100);
18+
Map<double, AnimatedConfig> slideOutUp = createSlideOut(AnimatedType.translateY, -100);
19+
Map<double, AnimatedConfig> slideOutLeft = createSlideOut(AnimatedType.translateX, -100);
20+
Map<double, AnimatedConfig> slideOutRight = createSlideOut(AnimatedType.translateY, 100);
21+
22+
Map<double, AnimatedConfig> slideInDown = createSlide(AnimatedType.translateY, 100);
23+
Map<double, AnimatedConfig> slideInUp = createSlide(AnimatedType.translateY, -100);
24+
Map<double, AnimatedConfig> slideInLeft = createSlide(AnimatedType.translateX, -100);
25+
Map<double, AnimatedConfig> slideInRight = createSlide(AnimatedType.translateY, 100);

lib/zooming.dart

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import 'package:flutter/material.dart';
2+
import 'animated_config.dart';
3+
import 'dart:math';
4+
5+
Curve zoomingCurve = Cubic(0.175, 0.885, 0.32, 1);
6+
7+
Map<double, AnimatedConfig> createZooming(AnimatedType type, double pivotPoint) {
8+
double modifier = min(1, max(-1, pivotPoint));
9+
return {
10+
0: AnimatedConfig(
11+
opacity: 0,
12+
scale: 0.1,
13+
translateX: type == AnimatedType.translateX ? modifier * -1000 : 0,
14+
translateY: type == AnimatedType.translateY ? modifier * -1000 : 0,
15+
),
16+
0.6: AnimatedConfig(
17+
opacity: 1,
18+
scale: 0.457,
19+
translateX: type == AnimatedType.translateX ? pivotPoint : 0,
20+
translateY: type == AnimatedType.translateY ? pivotPoint : 0,
21+
),
22+
1: AnimatedConfig(
23+
scale: 1,
24+
)
25+
};
26+
}
27+
28+
Map<double, AnimatedConfig> createZoomingOut(AnimatedType type, double pivotPoint) {
29+
double modifier = min(1, max(-1, pivotPoint));
30+
return {
31+
1: AnimatedConfig(
32+
opacity: 0,
33+
scale: 0.1,
34+
translateX: type == AnimatedType.translateX ? modifier * -1000 : 0,
35+
translateY: type == AnimatedType.translateY ? modifier * -1000 : 0,
36+
),
37+
0.4: AnimatedConfig(
38+
opacity: 1,
39+
scale: 0.457,
40+
translateX: type == AnimatedType.translateX ? pivotPoint : 0,
41+
translateY: type == AnimatedType.translateY ? pivotPoint : 0,
42+
),
43+
0: AnimatedConfig(
44+
scale: 1,
45+
)
46+
};
47+
}
48+
49+
Map<double, AnimatedConfig> zoomOutDown = createZoomingOut(AnimatedType.translateY, 60);
50+
51+
Map<double, AnimatedConfig> zoomOutUp = createZoomingOut(AnimatedType.translateY, -60);
52+
53+
Map<double, AnimatedConfig> zoomOutLeft = createZoomingOut(AnimatedType.translateX, 10);
54+
55+
Map<double, AnimatedConfig> zoomOutRight = createZoomingOut(AnimatedType.translateX, -10);
56+
57+
Map<double, AnimatedConfig> zoomInDown = createZooming(AnimatedType.translateY, 60);
58+
59+
Map<double, AnimatedConfig> zoomInUp = createZooming(AnimatedType.translateY, -60);
60+
61+
Map<double, AnimatedConfig> zoomInLeft = createZooming(AnimatedType.translateX, 10);
62+
63+
Map<double, AnimatedConfig> zoomInRight = createZooming(AnimatedType.translateX, -10);

0 commit comments

Comments
 (0)