transitions.dart 7.33 KB
Newer Older
1 2 3 4
// 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.

Hixie's avatar
Hixie committed
5 6
import 'dart:math' as math;

7
import 'package:flutter/animation.dart';
8
import 'package:flutter/rendering.dart';
Hixie's avatar
Hixie committed
9
import 'package:vector_math/vector_math_64.dart' show Matrix4;
10

11 12 13
import 'basic.dart';
import 'framework.dart';

14
export 'package:flutter/animation.dart' show AnimationDirection;
15
export 'package:flutter/rendering.dart' show RelativeRect;
16

17 18
abstract class TransitionComponent extends StatefulComponent {
  TransitionComponent({
19
    Key key,
20 21 22
    this.performance
  }) : super(key: key) {
    assert(performance != null);
23 24
  }

25
  final PerformanceView performance;
26

27
  Widget build(BuildContext context);
28

29
  _TransitionState createState() => new _TransitionState();
Hixie's avatar
Hixie committed
30 31 32 33 34

  void debugFillDescription(List<String> description) {
    super.debugFillDescription(description);
    description.add('performance: $performance');
  }
35 36
}

37
class _TransitionState extends State<TransitionComponent> {
38 39 40
  void initState() {
    super.initState();
    config.performance.addListener(_performanceChanged);
41
  }
42

43 44 45 46
  void didUpdateConfig(TransitionComponent oldConfig) {
    if (config.performance != oldConfig.performance) {
      oldConfig.performance.removeListener(_performanceChanged);
      config.performance.addListener(_performanceChanged);
47
    }
48
  }
49

50 51 52 53 54
  void dispose() {
    config.performance.removeListener(_performanceChanged);
    super.dispose();
  }

55 56 57 58
  void _performanceChanged() {
    setState(() {
      // The performance's state is our build state, and it changed already.
    });
59 60
  }

61 62
  Widget build(BuildContext context) {
    return config.build(context);
63
  }
64 65
}

66 67
abstract class TransitionWithChild extends TransitionComponent {
  TransitionWithChild({
68 69
    Key key,
    this.child,
70
    PerformanceView performance
71 72
  }) : super(key: key, performance: performance);

73
  final Widget child;
74

75
  Widget build(BuildContext context) => buildWithChild(context, child);
76

77
  Widget buildWithChild(BuildContext context, Widget child);
78 79
}

80
class SlideTransition extends TransitionWithChild {
81
  SlideTransition({
82 83
    Key key,
    this.position,
84
    PerformanceView performance,
85 86 87 88 89
    Widget child
  }) : super(key: key,
             performance: performance,
             child: child);

90
  final AnimatedValue<Point> position;
91

92
  Widget buildWithChild(BuildContext context, Widget child) {
93
    performance.updateVariable(position);
94 95 96 97 98 99
    Matrix4 transform = new Matrix4.identity()
      ..translate(position.value.x, position.value.y);
    return new Transform(transform: transform, child: child);
  }
}

Hixie's avatar
Hixie committed
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
class RotationTransition extends TransitionWithChild {
  RotationTransition({
    Key key,
    this.turns,
    PerformanceView performance,
    Widget child
  }) : super(key: key,
             performance: performance,
             child: child);

  final AnimatedValue<double> turns;

  Widget buildWithChild(BuildContext context, Widget child) {
    performance.updateVariable(turns);
    Matrix4 transform = new Matrix4.rotationZ(turns.value * math.PI * 2.0);
    return new Transform(
      transform: transform,
      alignment: const FractionalOffset(0.5, 0.5),
      child: child
    );
  }
}

123
class FadeTransition extends TransitionWithChild {
124
  FadeTransition({
125 126
    Key key,
    this.opacity,
127
    PerformanceView performance,
128 129 130 131 132
    Widget child
  }) : super(key: key,
             performance: performance,
             child: child);

133
  final AnimatedValue<double> opacity;
134

135
  Widget buildWithChild(BuildContext context, Widget child) {
136
    performance.updateVariable(opacity);
137 138 139 140
    return new Opacity(opacity: opacity.value, child: child);
  }
}

141
class ColorTransition extends TransitionWithChild {
142 143 144
  ColorTransition({
    Key key,
    this.color,
145
    PerformanceView performance,
146 147 148 149 150
    Widget child
  }) : super(key: key,
             performance: performance,
             child: child);

151
  final AnimatedColorValue color;
152

153
  Widget buildWithChild(BuildContext context, Widget child) {
154
    performance.updateVariable(color);
155 156 157 158 159 160
    return new DecoratedBox(
      decoration: new BoxDecoration(backgroundColor: color.value),
      child: child
    );
  }
}
161

162
class SquashTransition extends TransitionWithChild {
163 164 165 166
  SquashTransition({
    Key key,
    this.width,
    this.height,
167
    PerformanceView performance,
168 169 170 171 172
    Widget child
  }) : super(key: key,
             performance: performance,
             child: child);

173 174
  final AnimatedValue<double> width;
  final AnimatedValue<double> height;
175

176
  Widget buildWithChild(BuildContext context, Widget child) {
177
    if (width != null)
178
      performance.updateVariable(width);
179
    if (height != null)
180
      performance.updateVariable(height);
181
    return new SizedBox(width: width?.value, height: height?.value, child: child);
182 183
  }
}
184

185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
class AlignTransition extends TransitionWithChild {
  AlignTransition({
    Key key,
    this.alignment,
    this.widthFactor,
    this.heightFactor,
    PerformanceView performance,
    Widget child
  }) : super(key: key,
             performance: performance,
             child: child);

  final AnimatedValue<FractionalOffset> alignment;
  final AnimatedValue<double> widthFactor;
  final AnimatedValue<double> heightFactor;

  Widget buildWithChild(BuildContext context, Widget child) {
    if (alignment != null)
      performance.updateVariable(alignment);
    if (widthFactor != null)
      performance.updateVariable(widthFactor);
    if (heightFactor != null)
      performance.updateVariable(heightFactor);
    return new Align(
      alignment: alignment?.value,
      widthFactor: widthFactor?.value,
      heightFactor: heightFactor?.value,
212 213
      child: child
    );
214 215 216
  }
}

217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
/// An animated variable containing a RelativeRectangle
///
/// This class specializes the interpolation of AnimatedValue<RelativeRect> to
/// be appropriate for rectangles that are described in terms of offsets from
/// other rectangles.
class AnimatedRelativeRectValue extends AnimatedValue<RelativeRect> {
  AnimatedRelativeRectValue(RelativeRect begin, { RelativeRect end, Curve curve, Curve reverseCurve })
    : super(begin, end: end, curve: curve, reverseCurve: reverseCurve);

  RelativeRect lerp(double t) => RelativeRect.lerp(begin, end, t);
}

/// Animated version of [Positioned].
/// Only works if it's the child of a [Stack].
class PositionedTransition extends TransitionWithChild {
  PositionedTransition({
    Key key,
    this.rect,
    PerformanceView performance,
    Widget child
  }) : super(key: key,
             performance: performance,
             child: child) {
    assert(rect != null);
  }

  final AnimatedRelativeRectValue rect;

  Widget buildWithChild(BuildContext context, Widget child) {
    performance.updateVariable(rect);
    return new Positioned(
      top: rect.value.top,
      right: rect.value.right,
      bottom: rect.value.bottom,
      left: rect.value.left,
      child: child
    );
  }
}


258
typedef Widget BuilderFunction(BuildContext context);
259

260
class BuilderTransition extends TransitionComponent {
261 262
  BuilderTransition({
    Key key,
263
    this.variables: const <AnimatedValue>[],
264
    this.builder,
265
    PerformanceView performance
266
  }) : super(key: key,
267
             performance: performance);
268

269 270
  final List<AnimatedValue> variables;
  final BuilderFunction builder;
271

272
  Widget build(BuildContext context) {
273 274
    for (int i = 0; i < variables.length; ++i)
      performance.updateVariable(variables[i]);
275
    return builder(context);
276 277
  }
}