Last active
October 9, 2021 14:47
-
-
Save rxlabz/8c711b55b8be6d26fa3b6decb9347924 to your computer and use it in GitHub Desktop.
Flutter Canvas - CANDY#021.1
This file contains 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'; | |
import 'dart:ui'; | |
import 'package:flutter/material.dart'; | |
void main() => runApp(const App()); | |
class App extends StatelessWidget { | |
const App({Key? key}) : super(key: key); | |
@override | |
Widget build(BuildContext context) => const MaterialApp( | |
home: MainScreen(), | |
debugShowCheckedModeBanner: false, | |
); | |
} | |
class MainScreen extends StatefulWidget { | |
const MainScreen({Key? key}) : super(key: key); | |
@override | |
State<MainScreen> createState() => _MainScreenState(); | |
} | |
class _MainScreenState extends State<MainScreen> | |
with SingleTickerProviderStateMixin { | |
late AnimationController anim; | |
@override | |
void initState() { | |
super.initState(); | |
anim = | |
AnimationController(vsync: this, duration: const Duration(seconds: 3)) | |
..repeat(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
final size = MediaQuery.of(context).size; | |
return Scaffold( | |
backgroundColor: Colors.grey.shade900, | |
body: AnimatedBuilder( | |
animation: anim, | |
builder: (context, snapshot) => CustomPaint( | |
size: size, | |
painter: WavePainter(anim.value), | |
), | |
), | |
); | |
} | |
} | |
const numLines = 29; | |
class WavePainter extends CustomPainter { | |
final double progress; | |
WavePainter(this.progress); | |
@override | |
void paint(Canvas canvas, Size size) { | |
for (var value in List.generate(numLines, (index) => index + 1)) { | |
final color = | |
HSLColor.fromAHSL(1, value / numLines * 360, .4, .5).toColor(); | |
final paint = Paint() | |
..color = color | |
..style = PaintingStyle.stroke; | |
drawWave( | |
canvas, | |
size: size, | |
numPoints: value + 2, | |
height: size.height / (value + 2), | |
stroke: paint, | |
fill: Paint()..color = color, | |
); | |
} | |
} | |
void drawWave( | |
Canvas canvas, { | |
required Size size, | |
required int numPoints, | |
required double height, | |
required Paint stroke, | |
required Paint fill, | |
}) { | |
final vGap = size.width / numPoints; | |
final centerY = size.height / 2; | |
final points = List.generate( | |
numPoints + 1, | |
(index) { | |
final y = centerY + | |
sin((progress * numPoints + index) * 2 * pi / numPoints) * height; | |
return Offset(index * vGap, y); | |
}, | |
); | |
var count = 0; | |
for (final point in points) { | |
if (count == points.length - 1) break; | |
if (point.dy <= centerY && points[count + 1].dy <= centerY) { | |
canvas.drawLine( | |
point, | |
points[count + 1], | |
Paint()..color = Colors.transparent, | |
); | |
} else if ((point.dy <= centerY && points[count + 1].dy >= centerY) || | |
(point.dy >= centerY && points[count + 1].dy <= centerY)) { | |
final bd = point.dy - points[count + 1].dy; | |
final ad = points[count + 1].dx - point.dx; | |
final oc = point.dy - centerY; | |
final middle = Offset((oc * ad / bd) + point.dx, centerY); | |
if (point.dy >= centerY) { | |
canvas.drawLine(point, middle, stroke); | |
} | |
if (points[count + 1].dy >= centerY) { | |
canvas.drawLine(middle, points[count + 1], stroke); | |
} | |
} else { | |
canvas.drawLine(point, points[count + 1], stroke); | |
} | |
count++; | |
} | |
for (final p in points.where((element) => element.dy < centerY)) { | |
final radius = 8 * (1 - (numPoints * 1.6 / (numLines * 1.7))); | |
canvas.drawCircle(p, radius, fill); | |
} | |
} | |
@override | |
bool shouldRepaint(covariant CustomPainter oldDelegate) { | |
return true; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment