我一直在尝试开发绘图应用程序,而所有示例代码(包括The Boring Flutter Development Show中的示例代码)都无法很好地转化为实际用途。
主要问题是CustomPaint
的绘制操作过于昂贵,并且会重新绘制每个点,每个帧。并且随着点数的增加,Flutter应用程序的每帧渲染时间显着增加
从我开始寻找解决此问题的方法开始,我就找到了这些
RepaintBoundary
:栅格化图层
使用SingleChildRenderObjectWidget
和RenderProxyBox
的自定义窗口小部件:必须实现绘画方法,并且无法传递控制器
我认为上述任何解决方案都无法满足我的需求:平滑的画布绘制操作而无需重新绘制。我什至尝试简化要点,但由于CustomPaint
如果有一种方法可以将画布作为小部件传递并附加控制器,则可以轻松地存储捕获的点并更有效地使用基本的画布操作,例如canvas.drawPath()
或canvas.drawLine()
>
任何建议都会有所帮助。谢谢!
答案 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(() {}));
}