Showing
1 changed file
with
47 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 | + |
-
Please register or login to post a comment