【问题标题】:Performance issue in drawing using Path Flutter使用 Path Flutter 绘图时的性能问题
【发布时间】:2020-08-11 05:18:47
【问题描述】:

我正在测试使用 Flutter 进行绘图的性能。我正在使用 Path 在 Listener 检测到的每个点之间画线,因为我已经读到使用它会提高性能。我正在使用 Listener,因为我通过将 kind 属性更改为 stylus 也尝试了 iPad 2017 上的 Apple Pencil。

问题是我希望在笔画设计中得到类似于 notability 的响应,它似乎慢得多,可以接受,但没有我想要的那么多。

所以我正在寻找提高速度方面的性能的技巧。

在以下链接中,他们建议使用 NotifyListener(),但我不明白如何继续。如果它真的提高了性能,我什至想要一个能够实现它的例子。 如果 Flutter 在用手指或手写笔绘图时有一些限制,请告诉我。 performance issue in drawing using flutter

import 'dart:io';
import 'dart:ui';

import 'package:flutter/material.dart';

class DrawWidget extends StatefulWidget {
  @override
  _DrawWidgetState createState() => _DrawWidgetState();
}

class _DrawWidgetState extends State<DrawWidget> {
  Color selectedColor = Colors.black;
  double strokeWidth = 3.0;
  List<MapEntry<Path, Object>> pathList = List();
  StrokeCap strokeCap = (Platform.isAndroid) ? StrokeCap.butt : StrokeCap.round;
  double opacity = 1.0;

  Paint pa = Paint();

  @override
  Widget build(BuildContext context) {
    return Listener(
      child: CustomPaint(
        size: Size.infinite,
        painter: DrawingPainter(
          pathList: this.pathList,
        ),
      ),
      onPointerDown: (details) {
        if (details.kind == PointerDeviceKind.touch) {
          print('down');
          setState(() {
            Path p = Path();
            p.moveTo(details.localPosition.dx, details.localPosition.dy);
            pa.strokeCap = strokeCap;
            pa.isAntiAlias = true;
            pa.color = selectedColor.withOpacity(opacity);
            pa.strokeWidth = strokeWidth;
            pa.style = PaintingStyle.stroke;
            var drawObj = MapEntry<Path,Paint>(p, pa);
            pathList.add(drawObj);
          });
        }
      },
      onPointerMove: (details) {
        if (details.kind == PointerDeviceKind.touch) {
          print('move');
          setState(() {
            pathList.last.key.lineTo(details.localPosition.dx, details.localPosition.dy);
          });
        }
      },
      /*onPointerUp: (details) {
        setState(() {
        });
      },*/
    );
  }
}

class DrawingPainter extends CustomPainter {
  DrawingPainter({this.pathList});
  List<MapEntry<Path, Object>> pathList;
  @override
  void paint(Canvas canvas, Size size) {
    for(MapEntry<Path, Paint> m in pathList) {
      canvas.drawPath(m.key, m.value);
    }
  }

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

【问题讨论】:

    标签: flutter


    【解决方案1】:

    我认为你不应该使用 setState,而应该使用 Bloc 或 ChangeNotifier 或 smth 之类的状态管理。

    另外,只是用这个画一条路径:

    canvas.drawPath(m.key, m.value);

    仅适用于较小的笔划宽度,绘制时会留下一条看起来很奇怪的线条,里面充满了空白。

    我通过使用基于手势功能(onPanStart、onPanEnd、onPanUpdate)更新 UI 的 Bloc 来实现这一点。它包含一个我称为 CanvasPath 的数据模型的列表,它代表一条线(从 onPanStart 到 onPanEnd 事件),它包含该线的结果路径、偏移列表和用于绘制它的 Paint。

    最后,paint() 方法从这个 CanvasPath 对象中绘制每条路径,并在每个偏移量中绘制一个圆。

    ` 对每个 canvasPath 执行以下操作:

          canvas.drawPath(canvasPath.path, _paint);
    
            for (int i = 0; i < canvasPath.drawPoints.length - 1; i++) {
             
          //draw Circle on every Offset of user interaction
              canvas.drawCircle(
                  canvasPath.drawPoints[i],
                _raidus,
                  _paint);
    
            }`
    

    我为此写了一篇博客,其中有更详细的解释: https://ivanstajcer.medium.com/flutter-drawing-erasing-and-undo-with-custompainter-6d00fec2bbc2

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-10
      • 1970-01-01
      • 2018-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-27
      相关资源
      最近更新 更多