You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 17:57:24