Flutter CustomPaint绘制矩形出现异常线条的原因及解决方案
Flutter CustomPaint绘制等分矩形出现异常线条的原因与解决方案
问题原因
出现异常线条的核心原因是浮点运算的精度误差:
- 500除以34是无限循环小数(500/34≈14.7058823529...),无法用二进制浮点数精确表示;
- 循环中通过
i * blocSize.width累加计算矩形位置时,微小的误差会被逐步放大,导致相邻矩形之间出现肉眼可见的缝隙(本质是画布背景透过缝隙显露出来),或是矩形边缘重叠时的抗锯齿视觉效果。
解决方案
不需要扩展矩形尺寸,以下两种方法可从根源解决问题:
方法1:整数运算分配像素,彻底消除浮点误差
将画布尺寸转换为整数,按“基础尺寸+剩余像素分配”的方式计算每个矩形的大小,确保所有矩形刚好填满画布:
class MyPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { const div = 34; final totalWidth = size.width.toInt(); final totalHeight = size.height.toInt(); // 计算基础尺寸和剩余需要分配的像素数 final baseWidth = totalWidth ~/ div; final remainingWidth = totalWidth % div; final baseHeight = totalHeight ~/ div; final remainingHeight = totalHeight % div; int currentX = 0; for (int i = 0; i < div; i++) { int currentY = 0; // 前remainingWidth个矩形多分配1像素,确保总宽度刚好填满 final width = baseWidth + (i < remainingWidth ? 1 : 0); for (int j = 0; j < div; j++) { // 前remainingHeight个矩形多分配1像素,确保总高度刚好填满 final height = baseHeight + (j < remainingHeight ? 1 : 0); canvas.drawRect( Rect.fromLTWH( currentX.toDouble(), currentY.toDouble(), width.toDouble(), height.toDouble(), ), Paint() ..color = Colors.red ..style = PaintingStyle.fill, ); currentY += height; } currentX += width; } } @override bool shouldRepaint(covariant CustomPainter oldDelegate) => false; }
方法2:合并路径绘制,自动消除缝隙
用Path将所有矩形区域合并为一个整体,一次性填充,即使存在微小浮点误差,路径合并也会自动消除缝隙:
class MyPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { const div = 34; final blocWidth = size.width / div; final blocHeight = size.height / div; final path = Path(); for (int i = 0; i < div; i++) { for (int j = 0; j < div; j++) { path.addRect(Rect.fromLTWH( i * blocWidth, j * blocHeight, blocWidth, blocHeight, )); } } canvas.drawPath(path, Paint()..color = Colors.red); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) => false; }
补充说明
- 方法1适合对像素精度要求极高的场景,完全避免浮点运算误差;
- 方法2实现更简洁,利用Flutter的Path合并特性自动处理缝隙问题。
内容的提问来源于stack exchange,提问作者Md. Yeasin Sheikh
相关产品推荐
相关产品推荐

