How to animate a drawPaint using a custom painter?

I want to achieve this:

gif

This is my code:

import 'package:flutter/material.dart';
import 'dart:math' as math;

class CustomTimePainter extends CustomPainter {
  CustomTimePainter({
    required this.animation,
    required this.backgroundColor,
    required this.color,
  }) : super(repaint: animation);

  final Animation<double> animation;
  final Color backgroundColor, color;

  @override
  void paint(Canvas canvas, Size size) {
    var paint = Paint()
      ..color = const Color.fromARGB(255, 204, 255, 86);
    canvas.drawPaint(paint);

    var paintHourglassAnimation = Paint()
    ..color = Colors.blue;

    canvas.drawPaint(paintHourglassAnimation);

  }

  @override
  bool shouldRepaint(CustomTimePainter old) {
    return animation.value != old.animation.value ||
        color != old.color ||
        backgroundColor != old.backgroundColor;
  }
}

This in my man screen:

 class MainScreen extends StatefulWidget {
    const MainScreen({Key? key}) : super(key: key);
    
    @override
    State<MainScreen> createState() => _MainScreenState();
    }
    
    class _MainScreenState extends State<MainScreen> with TickerProviderStateMixin {
    final CountDownController _countDownController = Get.find();
    final ProjectsController _projectsController = Get.find();
    final SettingsController _settingsController = Get.find();
    
    
    
    @override
    void initState() {
    super.initState();
    _countDownController.createAnimationController(this);
    }
    
    @override
    Widget build(BuildContext context) {
    return Scaffold(
    backgroundColor: Colors.white10,
    body: Center(
    child: AnimatedBuilder(
    animation: _countDownController.controller,
    builder: (context, child) {
      return Stack(
        children: [
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
           Expanded(
              flex: 50,
              child: Padding(
                padding: const EdgeInsets.all(20.0),
                child: Align(
                  alignment: FractionalOffset.center,
                  child: AspectRatio(
                    aspectRatio: 1.0,
                    child: Stack(
                        children: <Widget>[
                          Positioned.fill(
                            child: CustomPaint(
                                painter:
                                    _countDownController.painter),
                          ),
                          Align(
                            alignment: FractionalOffset.center,
                            child: Column(
                              mainAxisAlignment:
                                  MainAxisAlignment.spaceEvenly,
                              crossAxisAlignment:
                                  CrossAxisAlignment.center,
                              children: <Widget>[
                                Obx(
                                  () => Text(
                                    _countDownController
                                        .timerString.value,
                                    style: const TextStyle(
                                        fontSize: 80.0,
                                        color: Colors.white),
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ],
                      ),
  
                  ),
                ),
              ),
            ),
          ]

I’m using this custom paint to try to achieve the animation above if I decide to start a timer and the animation start to fade like an hourglass timer.

I don’t know how to implement this package: import 'dart:math' as math; to program the animation

How can I animate the var paintHourglassAnimation to have the hourglass transition like the video above?

Thanks for any help you can provide

>Solution :

You can draw paint like

import 'dart:ui' as ui;

class CustomTimePainter extends CustomPainter {
  CustomTimePainter({
    required this.animation,
    required this.backgroundColor,
    required this.color,
  }) : super(repaint: animation);

  final Animation<double> animation;
  final Color backgroundColor, color;

  @override
  void paint(Canvas canvas, Size size) {
    var paint = Paint()..color = backgroundColor;
    canvas.drawPaint(paint);

    final top = ui.lerpDouble(0, size.height, animation.value)!;
    Rect rect = Rect.fromLTRB(0, top, size.width, size.height);
    Path path = Path()..addRect(rect);

    canvas.drawPath(path, paint..color = color);
  }

  @override
  bool shouldRepaint(CustomTimePainter old) {
    return animation.value != old.animation.value ||
        color != old.color ||
        backgroundColor != old.backgroundColor;
  }
}

And example output


class ANTest extends StatefulWidget {
  const ANTest({super.key});

  @override
  State<ANTest> createState() => _ANTestState();
}

class _ANTestState extends State<ANTest> with SingleTickerProviderStateMixin {
  late AnimationController container =
      AnimationController(vsync: this, duration: Duration(seconds: 3))
        ..repeat();

  late Animation<double> animation =
      Tween<double>(begin: 0, end: 1).animate(container);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: LayoutBuilder(
        builder: (_, constraints) => CustomPaint(
          size: constraints.biggest,
          painter: CustomTimePainter(
            color: Colors.amber,
            backgroundColor: Colors.black,
            animation: animation,
          ),
        ),
      ),
    );
  }
}

Leave a Reply