Skip to content

Instantly share code, notes, and snippets.

@rxlabz
Last active October 9, 2021 14:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rxlabz/8c711b55b8be6d26fa3b6decb9347924 to your computer and use it in GitHub Desktop.
Save rxlabz/8c711b55b8be6d26fa3b6decb9347924 to your computer and use it in GitHub Desktop.
Flutter Canvas - CANDY#021.1
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