Created
January 21, 2019 17:34
-
-
Save brianegan/7cf170efc186b78065dcf70db00b613c to your computer and use it in GitHub Desktop.
A pretty cool spinner for Flutter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:math' show pi; | |
import 'package:flutter/material.dart'; | |
class Spinnies extends StatefulWidget { | |
final Duration duration; | |
final Size size; | |
final double strokeWidth; | |
final List<SpinRect> rects; | |
const Spinnies({ | |
Key key, | |
@required this.duration, | |
@required this.size, | |
@required this.strokeWidth, | |
@required this.rects, | |
}) : super(key: key); | |
@override | |
_SpinniesState createState() => _SpinniesState(); | |
} | |
class _SpinniesState extends State<Spinnies> | |
with SingleTickerProviderStateMixin { | |
AnimationController _controller; | |
@override | |
void initState() { | |
_controller = AnimationController(vsync: this, duration: widget.duration) | |
..forward() | |
..repeat(); | |
super.initState(); | |
} | |
@override | |
void dispose() { | |
_controller.dispose(); | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
backgroundColor: Colors.black, | |
body: Center( | |
child: SizedBox( | |
width: widget.size.width, | |
height: widget.size.height, | |
child: CustomPaint( | |
painter: SpinniesPainter( | |
rects: widget.rects, | |
animation: _controller, | |
), | |
), | |
), | |
), | |
); | |
} | |
} | |
class SpinniesPainter extends CustomPainter { | |
final List<SpinRect> rects; | |
final Animation<double> animation; | |
SpinniesPainter({ | |
@required this.rects, | |
@required this.animation, | |
}) : super(repaint: animation); | |
@override | |
void paint(Canvas canvas, Size size) { | |
final rrect = RRect.fromLTRBAndCorners( | |
0.0, | |
0.0, | |
size.width, | |
size.height, | |
topLeft: Radius.elliptical( | |
size.width * 1.15, | |
size.height * 1.25, | |
), | |
topRight: Radius.elliptical( | |
size.width * 1.40, | |
size.height * 1.40, | |
), | |
bottomRight: Radius.elliptical( | |
size.width * 1.45, | |
size.height * 1.10, | |
), | |
bottomLeft: Radius.elliptical( | |
size.width * 1.10, | |
size.height * 1.25, | |
), | |
); | |
for (final rect in rects) { | |
canvas.save(); | |
canvas.translate(size.width / 2, size.height / 2); | |
canvas.rotate(rect.tween.lerp(animation.value) * pi * 2); | |
canvas.translate(-size.width / 2, -size.height / 2); | |
canvas.drawRRect( | |
rrect, | |
Paint() | |
..blendMode = BlendMode.screen | |
..strokeWidth = rect.strokeWidth | |
..style = PaintingStyle.stroke | |
..color = rect.color); | |
canvas.restore(); | |
} | |
} | |
@override | |
bool shouldRepaint(SpinniesPainter oldDelegate) { | |
return true; | |
} | |
} | |
class SpinRect { | |
final Color color; | |
final double strokeWidth; | |
final Tween<double> tween; | |
SpinRect({ | |
@required this.color, | |
@required double begin, | |
@required double end, | |
this.strokeWidth = 7.0, | |
}) : tween = Tween<double>(begin: begin, end: end); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment