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

Flutter Canvas如何高效绘制大量不同颜色的Raw Points

快速绘制大量带自定义颜色的点

直接使用drawRawPoints无法为单个点指定不同颜色,因为它仅接受单一Paint对象。逐个绘制点性能太差,这里推荐两种高效方案:

方案一:按颜色分组批量绘制

把相同颜色的点归类到同一组,对每组颜色调用一次drawRawPoints。这样绘制次数等于颜色种类数,远小于总点数,能大幅提升性能。

修改后的代码示例:

void _paintPoints(Canvas canvas, List matrix, Size size) {
  final width = size.width / matrix.length;
  final height = size.height / matrix.first.length;
  // 用Map按颜色分组存储点坐标
  final Map<Color, List<double>> colorToPoints = {};

  for (var i = 0; i < matrix.length; i++) {
    for (var j = 0; j < matrix[i].length; j++) {
      final x = i * width;
      final y = j * height;
      final color = Color.fromARGB(
        matrix[i][j][3],
        matrix[i][j][0],
        matrix[i][j][1],
        matrix[i][j][2],
      );
      
      // 将点添加到对应颜色的分组中
      colorToPoints.putIfAbsent(color, () => []);
      colorToPoints[color]!.add(x);
      colorToPoints[color]!.add(y);
    }
  }

  // 遍历每个颜色分组,批量绘制点
  colorToPoints.forEach((color, points) {
    final floatPoints = Float32List.fromList(points);
    canvas.drawRawPoints(
      PointMode.points,
      floatPoints,
      Paint()
        ..color = color
        ..blendMode = BlendMode.srcOver
        ..strokeWidth = 2.0,
    );
  });
}

方案二:使用Image一次性绘制

如果颜色种类极多,分组效果有限,可以先将所有点绘制到一个Image对象中,再把整个Image画到Canvas上。这种方式只需要一次Canvas绘制操作,性能最优,但需要处理图像的创建与销毁:

Future<Image> _createPointsImage(List matrix, Size size) async {
  final width = size.width / matrix.length;
  final height = size.height / matrix.first.length;
  final recorder = PictureRecorder();
  final canvas = Canvas(recorder);

  // 按颜色分组绘制到PictureRecorder
  final colorToPoints = <Color, List<double>>{};
  for (var i = 0; i < matrix.length; i++) {
    for (var j = 0; j < matrix[i].length; j++) {
      final x = i * width;
      final y = j * height;
      final color = Color.fromARGB(
        matrix[i][j][3],
        matrix[i][j][0],
        matrix[i][j][1],
        matrix[i][j][2],
      );
      colorToPoints.putIfAbsent(color, () => []);
      colorToPoints[color]!.add(x);
      colorToPoints[color]!.add(y);
    }
  }

  colorToPoints.forEach((color, points) {
    canvas.drawRawPoints(
      PointMode.points,
      Float32List.fromList(points),
      Paint()
        ..color = color
        ..strokeWidth = 2.0,
    );
  });

  final picture = recorder.endRecording();
  return picture.toImage(size.width.floor(), size.height.floor());
}

// 在Widget中使用示例:
late Image pointsImage;

@override
void initState() {
  super.initState();
  _createPointsImage(yourMatrix, yourSize).then((image) {
    setState(() => pointsImage = image);
  });
}

@override
void dispose() {
  pointsImage.dispose();
  super.dispose();
}

void _paintPoints(Canvas canvas, Size size) {
  if (pointsImage != null) {
    canvas.drawImage(pointsImage, Offset.zero, Paint());
  }
}

注意:方案二适合点数据不频繁更新的场景,如果点需要实时刷新,方案一的性能表现更均衡。

内容的提问来源于stack exchange,提问作者MaLa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 16:37:26