0

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

Md. Yeasin Sheikh
  • 54,221
  • 7
  • 29
  • 56
caroc
  • 45
  • 7

1 Answers1

0

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,
          ),
        ),
      ),
    );
  }
}
Md. Yeasin Sheikh
  • 54,221
  • 7
  • 29
  • 56
  • My pleasure, you can find more about [CustomPainter](https://api.flutter.dev/flutter/rendering/CustomPainter-class.html) and [lerp](https://api.flutter.dev/flutter/dart-ui/Color/lerp.html) – Md. Yeasin Sheikh Jan 24 '23 at 20:03
  • 1
    actually you don't need `Tween` - you can pass your animation controller – pskink Jan 24 '23 at 20:23
  • @pskink wow, it works with `AnimationController` – Md. Yeasin Sheikh Jan 24 '23 at 20:27
  • 1
    @YeasinSheikh this is becaues `AnimationController` extends `Animation` see how i am passing animation controller to `ClockDelegate` here: https://gist.github.com/pskink/d1f591eca19359c09d38bf8cc35df4ca#file-clock-dart-L141 – pskink Jan 24 '23 at 20:31
  • Thanks, got it. And nice clock – Md. Yeasin Sheikh Jan 24 '23 at 20:43
  • those logics are (currently)complex to me, `composeMatrixFromOffsets` is the magic method here i think – Md. Yeasin Sheikh Jan 24 '23 at 20:57
  • yea, middle circle is the main handler here, bottom is getting like lower and top one is small factions while rotating. Firstly, I thought everyone has its own area. – Md. Yeasin Sheikh Jan 24 '23 at 21:01
  • btw if you want to know more about those matrix transforms run those examples: https://gist.github.com/pskink/aa0b0c80af9a986619845625c0e87a67 – pskink Jan 24 '23 at 21:05
  • thanks, I will start from here – Md. Yeasin Sheikh Jan 24 '23 at 21:07
  • Hello @YeasinSheikh, I have a quick question for you, do you know how to start the animation from the `CustomTimePainter` from top to bottom? – caroc Jan 24 '23 at 22:01
  • @caroc you mean fixed on top part? Replace `Rect rect = Rect.fromLTRB(0, top, size.width, size.height);` with `Rect rect = Rect.fromLTRB(0, 0, size.width,top);` here `top` referring to the bottom(height) of the paint. – Md. Yeasin Sheikh Jan 24 '23 at 22:04
  • @YeasinSheikh I'm sorry but didn't work, by the way, thank you for the answer, here I created a new answer because maybe I didn't explain it well https://stackoverflow.com/questions/75228123/how-to-start-an-animation-from-top-to-bottom – caroc Jan 25 '23 at 00:37
  • My mistake it was supposed to be `Rect.fromLTRB(0, top, size.width, size.height);` – Md. Yeasin Sheikh Jan 25 '23 at 00:59
  • 1
    btw i would forget: you don't need that complex `shouldRepaint` too - `bool shouldRepaint(CustomTimePainter painter) => false;` is just fine – pskink Jan 25 '23 at 04:59