如何使用 onPanUpdate 调用缩放 GestureDetector?

How to zoom a GestureDetector with onPanUpdate call?

我正在开发一个绘图应用程序。我想在 canvas 上启用绘图和缩放绘图。到目前为止,我尝试通过在 InteractiveViewer 中包装 GestureDetector 并使用 AbsorbPointer 打开和关闭缩放模式来实现它。请参阅下面的最小演示代码。

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

void main() => runApp(new MaterialApp(
  home: new IssueExamplePage(),
  debugShowCheckedModeBanner: false,
));

class IssueExamplePage extends StatefulWidget {
  @override
  _IssueExamplePageState createState() => _IssueExamplePageState();
}

class _IssueExamplePageState extends State<IssueExamplePage> {
  bool drawingBlocked = false;
  List<Offset> points = [];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Container(
          color: Colors.grey,
          padding: EdgeInsets.all(5),
          child: Container(
            color: Colors.white,
            child: InteractiveViewer(
              child: AbsorbPointer(
                absorbing: drawingBlocked,
                child: GestureDetector(
                  behavior: HitTestBehavior.translucent,
                  onPanUpdate: (details) {
                    RenderBox renderBox = context.findRenderObject();
                    Offset cursorLocation = renderBox.globalToLocal(details.localPosition);

                    setState(() {
                      points = List.of(points)..add(cursorLocation);
                    });
                  },
                  onPanEnd: (details) {
                    setState(() {
                      points = List.of(points)..add(null);
                    });
                  },
                  child: CustomPaint(
                    painter: MyPainter(points),
                    size: Size.infinite
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
      floatingActionButton: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          FloatingActionButton(
            child: Icon(drawingBlocked? CupertinoIcons.hand_raised_fill : CupertinoIcons.hand_raised),
            onPressed: () {
              setState(() {
                drawingBlocked = !drawingBlocked;
              });
            }
          ),
          SizedBox(
            height: 10
          ),
          FloatingActionButton(
            child: Icon(Icons.clear),
            onPressed: () {
              setState(() {
                points = [];
              });
            }
          ), 
          SizedBox(
            height: 20
          ),
        ],
      ),
    );
  }
}

class MyPainter extends CustomPainter {
  MyPainter(this.points);
  List<Offset> points;
  Paint paintBrush = Paint()
    ..color = Colors.blue
    ..strokeWidth = 5
    ..strokeJoin = StrokeJoin.round
    ..strokeCap = StrokeCap.round;

  @override
  void paint(Canvas canvas, Size size) {
    for (int i = 0; i < points.length - 1; i++) {
      if (points[i] != null && points[i + 1] != null) {
        canvas.drawLine(points[i], points[i + 1], paintBrush);
      }
    }
  }
  
  @override
  bool shouldRepaint(MyPainter oldDelegate) {
    return points != oldDelegate.points;
  }
}

但是,有了这个实现,OnPanUpdate 会延迟工作(请参阅 Flutter onPanStart invokes late when the widget is wrapped inside InteractiveViewer)。是否有任何其他方法可以达到预期的结果(缩放和绘图),或者是否可以修复 OnPanUpdate 延迟?

更新:我找到了某种解决方案。您可以使用 Listener 而不是 GestureDetector(它可以替代大部分参数:onPanStart -> onPointerDown、onPanUpdate -> onPointerMove 等)。但是 GestureDetector 似乎没有修复。