2

我一直在尝试开发一个绘图应用程序,所有示例代码,包括来自 The Boring Flutter Development Show 的示例代码都不能很好地转化为实际使用。

主要问题是它CustomPaint的绘制操作太昂贵并且重新绘制每一点、每一帧。随着点数的增加,颤振应用每帧的渲染时间显着增加

从我花时间寻找解决这个问题的方法开始,我发现了这些

  1. RepaintBoundary: 栅格化图层

  2. Custom Widget using SingleChildRenderObjectWidgetand RenderProxyBox: 必须实现一个paint方法并且不能传递一个控制器

我认为上述任何解决方案都不能很好地满足我的需求:无需重新绘制即可顺利进行画布绘制操作。我什至尝试简化这些要点,但由于固有的机制,这也不起作用CustomPaint

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

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

4

2 回答 2

3

这是控制器类

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)的渲染速度非常慢(最多 18 毫秒)。一旦你开始一个新的中风,这个问题就会消失。我尝试在几个论坛上询问,这是我在挖掘颤振源代码后能想到的最好的方法。

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

于 2020-10-01T10:42:32.150 回答
0

一个有用的提示是添加 Timer.run(setState())。这样,它只会在可能的时候更新。而不是加载 update1 update2 update3...等。它加载 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(() {}));
}
于 2020-11-10T18:02:14.930 回答