Home > Software design >  CustomPaint Erase shape on hit with fade effect
CustomPaint Erase shape on hit with fade effect

Time:04-12

I try to erase my circle when I click on the canva. I would like to make it appeat again on a second click. Atm I have this:

class FadeEffect extends StatefulWidget {

  const FadeEffect({Key? key}) : super(key: key);

  @override
  State<FadeEffect> createState() => _FadeEffectState();
}

class _FadeEffectState extends State<FadeEffect> {
  double vOpacity = 1;

  @override
  void initState() {
    super.initState();
    Timer.periodic(const Duration(milliseconds: 100), (timer) {
      vOpacity -= 0.1;
      if (mounted) {
        setState(() {
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
            size: Size(MediaQuery.of(context).size.width,MediaQuery.of(context).size.height),
            painter: MyPainter(vOpacity: vOpacity),
            );
  }

}


class MyPainter extends CustomPainter {
  double vOpacity;

  MyPainter({
    required this.vOpacity
  });

  @override
  void paint(Canvas canvas, Size size) {
    canvas.clipRect(Rect.fromLTWH(0, 0, size.width, size.height));

    var paint = Paint()
      ..color = Color.fromRGBO(0, 0, 0, vOpacity)
      ..strokeWidth = 5
      ..style = PaintingStyle.stroke
      ..strokeCap = StrokeCap.round;

    canvas.drawCircle(Offset(size.width / 2, size.height / 2), 300, paint);

  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }

  @override
  bool hitTest(Offset position) {
    erase();
    return true;
  }

  void erase() {
  }

}

I change the opacity of the circle's color from 1 to 0 when I run the program (idk how to do it when I call erase() ...). The other problem is that my circle appears again once it reaches 0 opacity.

P.S: Is there an another way to erase than changing opacity ?

CodePudding user response:

If you just want to make the circle disappear without any affects you can wrap the CustomPaint with the Visibility widget which controls the Visibility of its child. But when you want to achieve a fading out affect you should use the AnimatedOpacity widget which animates any opacity changes.
Below is a stand-alone code sample in which I demonstrated the two ways. The UI shows two circles painted with CustomPaint which both disappear and appear again when its canvas is clicked. The first one uses AnimatedOpacity whereas the second one uses the Visibility widget:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Test',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  ScrollController controller = ScrollController();
  double _opacity = 1.0;
  bool _visible = true;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          SizedBox(
            height: 300,
            width: 300,
            child: AnimatedOpacity(
              duration: const Duration(
                seconds: 3,
              ),
              opacity: _opacity,
              child: GestureDetector(
                onTap: () {
                  setState(() {
                    _opacity = _opacity == 1 ? 0 : 1;
                  });
                },
                child: CustomPaint(
                  painter: MyPainter(),
                ),
              ),
            ),
          ),
          SizedBox(
            width: 300,
            height: 300,
            child: Visibility(
              maintainInteractivity: true,
              maintainSize: true,
              maintainAnimation: true,
              maintainState: true,
              visible: _visible,
              child: GestureDetector(
                onTap: () {
                  setState(() {
                    _visible = _visible ? false : true;
                  });
                },
                child: CustomPaint(
                  painter: MyPainter(),
                ),
              ),
            ),
          ),
          const Text(
            "Tap on the canvas, to make the circle appear or disappear",
          ),
        ],
      ),
    );
  }
}

class MyPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()..color = Colors.black;
    canvas.drawCircle(Offset(size.width / 2, size.height / 2), 100, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }
}
  • Related