import 'package:aitrainer_app/bloc/timer/timer_bloc.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'dart:math'; import 'package:google_fonts/google_fonts.dart'; final temperatureColors = [ const Color(0xFFB50DE2), // -20 Celsius , friggin cold const Color(0xFFAE0DE2), const Color(0xFF980DE2), const Color(0xFF8E0DE2), const Color(0xFF810DE2), const Color(0xFF7B0DE2), const Color(0xFF670DE2), const Color(0xFF570DE2), const Color(0xFF4A0DE2), const Color(0xFF410DE2), const Color(0xFF1D0DE2), const Color(0xFF0D4AE2), const Color(0xFF0D57E2), const Color(0xFF0D74E2), const Color(0xFF0DB8E2), const Color(0xFF0DD8E2), const Color(0xFF0DE2BB), const Color(0xFF0DE2A1), const Color(0xFF0DE284), const Color(0xFF0DE25E), const Color(0xFF0DE244), const Color(0xFF84E20D), const Color(0xFFC2E20D), const Color(0xFFE2DF0D), const Color(0xFFE2A10D), const Color(0xFFE2740D), const Color(0xFFE2510D), const Color(0xFFE22D0D), const Color(0xFFE2100D), const Color(0xFFE20D17), // 40 Celsius, rather be dead ]; // ignore: must_be_immutable class Clock extends StatelessWidget { final TimerBloc bloc; final List colors = temperatureColors; Clock({this.bloc}); // ignore: close_sinks final Paint paintSeconds = Paint() ..strokeCap = StrokeCap.butt ..style = PaintingStyle.stroke ..strokeWidth = 4 ..isAntiAlias = true; final Paint paintMinutes = Paint() ..strokeCap = StrokeCap.butt ..style = PaintingStyle.stroke ..strokeWidth = 4 ..isAntiAlias = true; final Paint paintHours = Paint() ..strokeCap = StrokeCap.butt ..style = PaintingStyle.stroke ..strokeWidth = 4 ..isAntiAlias = true; @override Widget build(BuildContext context) { return BlocBuilder(builder: (context, state) { if (state is TimerRunning) { return getLayout(bloc.state); } else { return Offstage(); } }); } Widget getLayout(TimerState state) { int duration = 300 - state.duration; int seconds = (duration % 60).floor(); int minutes = ((duration / 60) % 60).floor(); String secondStr = seconds.toString().padLeft(2, '0'); String time = minutes == 0 ? "$secondStr" : "$minutes:$secondStr"; return LayoutBuilder(builder: (context, constraints) { return Stack( alignment: Alignment.center, fit: StackFit.expand, children: [ Positioned( top: 37, left: (45 - time.length / 2 * 9).toDouble(), //seconds < 10 ? 37 : 30, child: Text( "$time", style: GoogleFonts.kosugi(color: colors[(seconds ~/ 2)], fontSize: 16), )), CustomPaint(painter: ArcPainter(minutes, paintMinutes, 5, constraints.maxHeight * 0.40, 0.15, colors)), CustomPaint(painter: ArcPainter(seconds, paintSeconds, 60, constraints.maxHeight * 0.34, 0.2, colors)), ], ); }); } } class ArcPainter extends CustomPainter { int _progress; Paint _paint; int _units; double _gap; List _gradient; Offset center; double _radius; Paint paintMarkerEmpty; ArcPainter( this._progress, this._paint, this._units, this._radius, this._gap, this._gradient, ) { this.paintMarkerEmpty = Paint() ..strokeCap = StrokeCap.butt ..style = PaintingStyle.stroke ..strokeWidth = this._paint.strokeWidth ..isAntiAlias = true; } @override void paint(Canvas canvas, Size size) { center = Offset(size.width / 2, size.height / 2); var rect = Rect.fromCircle(center: center, radius: this._radius); final gradient2 = new SweepGradient( startAngle: -pi / 2, endAngle: (-pi / 2) + (pi * 2), tileMode: TileMode.repeated, colors: this._gradient, ); this._paint.shader = gradient2.createShader(rect); this.paintMarkerEmpty.color = this._gradient[0].withOpacity(0.2); for (var i = 0; i < this._units; i++) { final double unit = 2 * pi / this._units; double start = unit * i; double to = (((2 * pi) / this._units) + unit); canvas.drawArc(rect, (-pi / 2 + start), to * 2 * this._gap, false, i < this._progress ? this._paint : this.paintMarkerEmpty); } } @override bool shouldRepaint(CustomPainter oldDelegate) { return true; } }