Committed by
GitHub
Merge pull request #2050 from jonataslaw/4.5.1
Circular reveal
Showing
3 changed files
with
86 additions
and
0 deletions
| 1 | +import 'dart:math' show sqrt, max; | ||
| 2 | +import 'dart:ui' show lerpDouble; | ||
| 3 | + | ||
| 4 | +import 'package:flutter/material.dart'; | ||
| 5 | + | ||
| 6 | +class CircularRevealClipper extends CustomClipper<Path> { | ||
| 7 | + final double fraction; | ||
| 8 | + final Alignment? centerAlignment; | ||
| 9 | + final Offset? centerOffset; | ||
| 10 | + final double? minRadius; | ||
| 11 | + final double? maxRadius; | ||
| 12 | + | ||
| 13 | + CircularRevealClipper({ | ||
| 14 | + required this.fraction, | ||
| 15 | + this.centerAlignment, | ||
| 16 | + this.centerOffset, | ||
| 17 | + this.minRadius, | ||
| 18 | + this.maxRadius, | ||
| 19 | + }); | ||
| 20 | + | ||
| 21 | + @override | ||
| 22 | + Path getClip(Size size) { | ||
| 23 | + final Offset center = this.centerAlignment?.alongSize(size) ?? | ||
| 24 | + this.centerOffset ?? | ||
| 25 | + Offset(size.width / 2, size.height / 2); | ||
| 26 | + final minRadius = this.minRadius ?? 0; | ||
| 27 | + final maxRadius = this.maxRadius ?? calcMaxRadius(size, center); | ||
| 28 | + | ||
| 29 | + return Path() | ||
| 30 | + ..addOval( | ||
| 31 | + Rect.fromCircle( | ||
| 32 | + center: center, | ||
| 33 | + radius: lerpDouble(minRadius, maxRadius, fraction)!, | ||
| 34 | + ), | ||
| 35 | + ); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + @override | ||
| 39 | + bool shouldReclip(CustomClipper<Path> oldClipper) => true; | ||
| 40 | + | ||
| 41 | + static double calcMaxRadius(Size size, Offset center) { | ||
| 42 | + final w = max(center.dx, size.width - center.dx); | ||
| 43 | + final h = max(center.dy, size.height - center.dy); | ||
| 44 | + return sqrt(w * w + h * h); | ||
| 45 | + } | ||
| 46 | +} | ||
| 47 | + | 
| @@ -184,3 +184,26 @@ class SizeTransitions { | @@ -184,3 +184,26 @@ class SizeTransitions { | ||
| 184 | ); | 184 | ); | 
| 185 | } | 185 | } | 
| 186 | } | 186 | } | 
| 187 | + | ||
| 188 | + | ||
| 189 | +class CircularRevealTransition { | ||
| 190 | + Widget buildTransitions( | ||
| 191 | + BuildContext context, | ||
| 192 | + Curve? curve, | ||
| 193 | + Alignment? alignment, | ||
| 194 | + Animation<double> animation, | ||
| 195 | + Animation<double> secondaryAnimation, | ||
| 196 | + Widget child) { | ||
| 197 | + return ClipPath( | ||
| 198 | + clipper: CircularRevealClipper( | ||
| 199 | + fraction: animation.value, | ||
| 200 | + centerAlignment: Alignment.center, | ||
| 201 | + centerOffset: Offset.zero, | ||
| 202 | + minRadius: 0, | ||
| 203 | + maxRadius: 800, | ||
| 204 | + ), | ||
| 205 | + child: child, | ||
| 206 | + ); | ||
| 207 | + } | ||
| 208 | +} | ||
| 209 | + | 
| @@ -619,6 +619,22 @@ Cannot read the previousTitle for a route that has not yet been installed''', | @@ -619,6 +619,22 @@ Cannot read the previousTitle for a route that has not yet been installed''', | ||
| 619 | onStartPopGesture: () => _startPopGesture<T>(route), | 619 | onStartPopGesture: () => _startPopGesture<T>(route), | 
| 620 | child: child) | 620 | child: child) | 
| 621 | : child); | 621 | : child); | 
| 622 | + | ||
| 623 | + case Transition.ciruclarReveal: | ||
| 624 | + return CircularRevealTransition().buildTransitions( | ||
| 625 | + context, | ||
| 626 | + route.curve, | ||
| 627 | + route.alignment, | ||
| 628 | + animation, | ||
| 629 | + secondaryAnimation, | ||
| 630 | + route.popGesture ?? Get.defaultPopGesture | ||
| 631 | + ? CupertinoBackGestureDetector<T>( | ||
| 632 | + gestureWidth: route.gestureWidth?.call(context) ?? | ||
| 633 | + _kBackGestureWidth, | ||
| 634 | + enabledCallback: () => _isPopGestureEnabled<T>(route), | ||
| 635 | + onStartPopGesture: () => _startPopGesture<T>(route), | ||
| 636 | + child: child) | ||
| 637 | + : child); | ||
| 622 | 638 | ||
| 623 | default: | 639 | default: | 
| 624 | if (Get.customTransition != null) { | 640 | if (Get.customTransition != null) { | 
- 
Please register or login to post a comment