在Flutter中高效的Canvas渲染

时间:2020-06-16 15:34:31

标签: flutter dart rxdart flutter-canvas

我一直在尝试开发绘图应用程序,而所有示例代码(包括The Boring Flutter Development Show中的示例代码)都无法很好地转化为实际用途。

主要问题是CustomPaint的绘制操作过于昂贵,并且会重新绘制每个点,每个帧。并且随着点数的增加,Flutter应用程序的每帧渲染时间显着增加

从我开始寻找解决此问题的方法开始,我就找到了这些

  1. RepaintBoundary:栅格化图层

  2. 使用SingleChildRenderObjectWidgetRenderProxyBox的自定义窗口小部件:必须实现绘画方法,并且无法传递控制器

我认为上述任何解决方案都无法满足我的需求:平滑的画布绘制操作而无需重新绘制。我什至尝试简化要点,但由于CustomPaint

的固有机制而没有用

如果有一种方法可以将画布作为小部件传递并附加控制器,则可以轻松地存储捕获的点并更有效地使用基本的画布操作,例如canvas.drawPath()canvas.drawLine()

任何建议都会有所帮助。谢谢!

2 个答案:

答案 0 :(得分:1)

这是Controller类

class DrawingController extends ChangeNotifier {

  List<Offset> _points = []
   
  .... // Perform operations on data points
  ....

  void add(Offset point) {
    _points.add(point);
    notifyListeners();
  }

}

这是CustomPaint

class Painter extends CustomPainter {
  DrawingController controller;

  Painter(this.controller) : super(repaint: controller); //This is important

  @override
  void paint(Canvas canvas, Size size) {
     //Paint function
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => true;
}

在手势检测器中,只需调用controller.add(point)即可在抓取它们时添加新点

我不确定这是最有效的绘画方式,但是在60Hz屏幕上将绘画时间减少到13ms,在120Hz屏幕上将绘画时间减少到9ms。一个明显的缺点是,当笔划有很多点时,单个笔划(onTapdownEvent到onDragEndEvent)渲染速度非常慢(最长18ms)。一旦开始新的中风,此问题就会消失。我曾尝试在多个论坛上提问,这是我在深入探究源代码后能想到的最好的方法。

我在snapdragon 855设备上介绍了此功能,因此处理器不是瓶颈。如果有人找到更好的解决方案,请发布它。

答案 1 :(得分:0)

一个有用的技巧是添加Timer.run(setState())。这样,它只会在可能的时候更新。而不是加载update1 update2 update3 ... etc。它加载update1,然后如果可以加载,则加载update2,但是如果update1花了很长时间,则转到update3。通常,它看起来更平滑,但不一定会加快速度。样本:

scaleStart(ScaleStartDetails d) => startPoint = d.focalPoint - _offset;

scaleUpdate(ScaleUpdateDetails d) {
  _offset = d.focalPoint - startPoint;
  scale = min(max(1, scale * (d.scale + 13) / 14), 128);
  Timer.run(() => setState(() {}));
}
相关问题