用颤振画布在形状上切出一个洞

Mat*_*sen 14 dart flutter flutter-canvas

如何使用颤振画布在形状上“切一个洞”?我有一组相当复杂的形状,看起来像一个真实世界的物体。这个物体有一个洞,形状像一个圆角矩形。

我真的很想从一个形状中减去一个 RRect,但我找不到任何关于如何做到这一点的信息。 canvas.clipRRect(myRRect)只是删除未覆盖的所有内容myRRect。我想要相反的。即myRRect在当前画布形状或形状中制作形状孔。

Yan*_*n39 18

您可以Path.combinedifference操作一起使用来创建孔。

自定义画家:

class HolePainter extends CustomPainter {

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint();
    paint.color = Colors.blue;
    canvas.drawPath(
        Path.combine(
          PathOperation.difference,
          Path()..addRRect(RRect.fromLTRBR(100, 100, 300, 300, Radius.circular(10))),
          Path()
            ..addOval(Rect.fromCircle(center: Offset(200, 200), radius: 50))
            ..close(),
        ),
        paint,
    );
  }

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

}
Run Code Online (Sandbox Code Playgroud)

用法 :

class EditAvatar extends StatelessWidget {

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: Text('Hole in rounded rectangle'),
      ),
      body: CustomPaint(
        painter: HolePainter(),
        child: Container(),
      ),

  }

}
Run Code Online (Sandbox Code Playgroud)

结果 :

在此处输入图片说明

当然,如果您希望孔是圆角矩形,只需减去 aRRect而不是 a Circle


小智 6

一个解决方案是使用PathFillType.evenOdd

// circle with empty RRect inside
final Path path = Path();
path.fillType = PathFillType.evenOdd;
path.addOval(Rect.fromCircle(center: center, radius: radius));
path.addRRect(RRect.fromRectAndRadius(
    Rect.fromCircle(center: center, radius: radius / 2),
    Radius.circular(radius / 10)));
canvas.drawPath(path, paint);
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明


Jig*_*gar 3

您可以在自定义画家中尝试不同的混合模式,下面是您可以参考的示例之一:

class MyPaint extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    // below one is big circle and instead of this circle you can draw your shape here.
    canvas.drawCircle(Offset(200, 200), 100, Paint()
      ..color = Colors.orange[200]
      ..style = PaintingStyle.fill);

    // below the circle which you want to create a cropping part.
    RRect rRect = RRect.fromRectAndRadius(Rect.fromCenter(center: Offset(200, 200), width: 75, height: 75), Radius.circular(8));
    canvas.drawRRect(rRect, Paint()
      ..color = Colors.orange[200]
      ..style = PaintingStyle.fill
      ..blendMode = BlendMode.dstOut);

    canvas.save();
    canvas.restore();
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}
Run Code Online (Sandbox Code Playgroud)

在这里,我使用了BlendMode.dstOutwhich 将用于显示目标源,但仅限于两个源不重叠的情况。

  • 谢谢你的建议。遗憾的是我找不到任何混合模式可以满足我的要求。他们中的一些人将最后一个形状绘制为顶部的黑色,但大多数人似乎什么也没做。 (2认同)