Флаттер: масштабирование и панорамирование виджета - PullRequest
1 голос
/ 28 января 2020

Я борюсь с масштабированием / панорамированием. Я нашел частично подходящий пример в этой книге:

https://books.google.bg/books?id=ex-tDwAAQBAJ&pg=PA284&lpg=PA284&dq=flutter+_startLastOffset&source=bl&ots=YUQna09jIf&sig=ACfU3U0QrHwl2RdrVUv5EtpHaHFKx_cXhA&hl=en&sa=X&ved=2ahUKEwid9uPJ8abnAhVnlosKHTKQBn4Q6AEwAHoECAMQAQ#v = onepage & q = flutter% 20_startLastOffset & f = false

, который, я думаю, был основан на этом: https://chromium.googlesource.com/external/github.com/flutter/flutter/+/refs/heads/dev/examples/layers/widgets/gestures.dart

И мой код на его основе:

Offset _startLastOffset = Offset.zero;
Offset _lastOffset = Offset.zero;
Offset _currentOffset = Offset.zero;
double _lastScale = 1.0;
double _currentScale = 1.0;

void _onScaleStart(ScaleStartDetails details) {
  _startLastOffset = details.focalPoint;
  _lastOffset = _currentOffset;
  _lastScale = _currentScale;
}

void _onScaleUpdate(ScaleUpdateDetails details) {
  if (details.scale != 1.0) {
    // Scaling
    double currentScale = _lastScale * details.scale;
    if (currentScale < 0.5) {
      currentScale = 0.5;
    }
    _currentScale = currentScale;
    _bloc.setScale(_currentScale);
  } else if (details.scale == 1.0) {
    // We are not scaling but dragging around screen
    // Calculate offset depending on current Image scaling.
    Offset offsetAdjustedForScale = (_startLastOffset - _lastOffset) / _lastScale;
    Offset currentOffset = details.focalPoint - (offsetAdjustedForScale * _currentScale);
    _currentOffset = currentOffset;
    _bloc.setOffset(_currentOffset);
  }
}
---------------
child: StreamBuilder<Object>(
  stream: _bloc.scale,
  builder: (context, snapshot1) {
    double _cscale = snapshot1.hasData? snapshot1.data : _currentScale;
    return StreamBuilder<Object>(
      stream: _bloc.offset,
      builder: (context, snapshot2) {
        Offset _coffset = snapshot2.hasData? snapshot2.data : _currentOffset;
        return Transform(
          transform: Matrix4.identity()
            ..scale(_cscale, _cscale)
            ..translate(_coffset.dx, _coffset.dy),
          alignment: FractionalOffset.center,
          child: Stack(
            key: _imgStack,
            fit: StackFit.expand,
            children: <Widget>[
              Image(image: AssetImage('assets/images/image.png')),
              SvgPicture.asset(svgFile)
            ],
          ),
        );
      }
    );
  }
),

Панорамирование, которое, однако, ведет себя неестественно, когда виджет масштабируется - виджет сильно перемещается дальше, чем палец, в направлении движения.

Мне удалось это исправить, изменив:

_currentOffset = currentOffset;
_bloc.setOffset(_currentOffset);

на:

_bloc.setOffset(currentOffset/_currentScale);
_currentOffset = currentOffset;

, который работает точно так, как ожидалось, но только до второго зума. После второго увеличения масштаба виджет смещается при первом касании. При увеличении он сдвигается вправо, при уменьшении он сдвигается влево.

Есть идеи?

...