CustomPaint 使用淡入淡出效果擦除形状

CustomPaint Erase shape on hit with fade effect

我试图在单击画布时擦除我的圆圈。我想让它在第二次点击时再次出现。自动取款机我有这个:

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() {
  }

}

当我 运行 程序时,我将圆圈颜色的不透明度从 1 更改为 0(不知道当我调用 erase() 时该怎么做...)。另一个问题是我的圆圈一旦达到 0 不透明度就会再次出现。

P.S: 除了改变不透明度还有其他擦除方法吗?

如果您只想让圆圈消失而不产生任何影响,您可以使用 Visibility 小部件包裹 CustomPaint 来控制其子项的可见性。但是当你想要实现淡出效果时,你应该使用 AnimatedOpacity 小部件来动画任何不透明度的变化。
下面是一个 stand-alone 代码示例,我在其中演示了这两种方法。 UI 显示两个涂有 CustomPaint 的圆圈,当单击其 canvas 时,它们会消失并再次出现。第一个使用 AnimatedOpacity 而第二个使用 Visibility 小部件:

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;
  }
}