Dart中使用Canvas从填充矩形中裁剪透明矩形的实现方法
Flutter Canvas 填充矩形挖透明区域实现方案
你原有代码无法生效的核心原因有两个:
- 用于挖除的矩形传入的四个坐标值全部为100,本质是尺寸为0的无效路径,无法挖出任何可见区域
- 路径组合的基底路径错误:差集运算规则是「前层路径减去后层路径」,你把要挖的小矩形作为基底,自然得不到整块遮罩挖洞的效果
正确实现逻辑
这类遮罩挖洞效果用Path.combine的PathOperation.difference(差集)运算实现是最稳妥的,不需要依赖特殊组件,核心逻辑是:
- 先绘制和目标区域等大的完整填充遮罩路径
- 定义需要挖成透明的区域路径
- 用差集运算从完整遮罩中剔除透明区域路径,最终把运算得到的路径绘制到画布即可
可复用的Painter代码
class HoleMaskPainter extends CustomPainter { /// 遮罩层颜色 final Color maskColor; /// 需要挖空的透明区域(支持圆角) final RRect transparentArea; HoleMaskPainter({ required this.maskColor, required this.transparentArea, }); @override void paint(Canvas canvas, Size size) { final maskPaint = Paint()..color = maskColor; // 构建覆盖整个绘制区域的遮罩基底路径 final fullMaskPath = Path()..addRect(Offset.zero & size); // 构建要挖空的区域路径 final holePath = Path()..addRRect(transparentArea); // 差集运算得到带透明洞的最终路径 final resultPath = Path.combine( PathOperation.difference, fullMaskPath, holePath, ); canvas.drawPath(resultPath, maskPaint); } @override bool shouldRepaint(covariant HoleMaskPainter oldDelegate) { return maskColor != oldDelegate.maskColor || transparentArea != oldDelegate.transparentArea; } }
调用示例
如果要实现蓝色半透明遮罩、中间挖出10px圆角透明矩形的效果,直接传入对应参数即可:
CustomPaint( // 传入你需要的遮罩尺寸 size: const Size(double.infinity, double.infinity), painter: HoleMaskPainter( maskColor: Colors.blue.withOpacity(0.7), // 定义透明洞的位置、尺寸、圆角 transparentArea: RRect.fromLTRBR( 100, 100, 300, 300, const Radius.circular(10) ), ), // 透明洞下方要显示的内容放在child里即可 child: const YourContentWidget(), )
扩展说明
- 如果需要挖直角矩形的透明区域,把洞路径的
addRRect替换为addRect即可,不需要传圆角参数 - 如果需要挖多个透明洞,先把所有洞的路径通过
PathOperation.union合并成单一路径,再做一次差集运算即可 - 不要用
canvas.clipPath/canvas.clipRect实现这类效果,裁剪操作会影响后续同画布的所有绘制内容,路径差集方案独立性更强,不会产生额外副作用
内容的提问来源于stack exchange,提问作者user16357470
相关产品推荐
相关产品推荐

