perlatus / flutter_zoomable_image

A plugin for panning and zooming images by touch.
ISC License
119 stars 43 forks source link

Image Zooms Out Too Far and Image Scrolls Out of Viewport #9

Open samvictor opened 7 years ago

samvictor commented 7 years ago

The user is able to zoom out until the image disappears. This fixed it for me:

I changed:

  void _handleScaleUpdate(Size size, ScaleUpdateDetails d) {
    double newZoom = _previousZoom * d.scale;
    bool tooZoomedIn = _image.width * _scale / newZoom <= size.width ||
        _image.height * _scale / newZoom <= size.height;

    if (tooZoomedIn) {
      return;
    }

to:

  void _handleScaleUpdate(Size size, ScaleUpdateDetails d) {
    double newZoom = _previousZoom * d.scale;
    bool tooZoomedIn = _image.width * _scale / newZoom <= size.width ||
        _image.height * _scale / newZoom <= size.height;

    // Too Zoomed Out
    if (newZoom < 0.9)
        newZoom = 0.9;

    if (tooZoomedIn) {
        return;
    }

where 0.9 is the "give" or "leeway" so that the image can zoom out a little.

Image Scrolls out of Viewport. I fixed this in the Horizontal direction, but not the vertical. In the same function, I changed:

// Ensure that item under the focal point stays in the same place despite zooming
    final Offset normalizedOffset =
        (_startingFocalPoint - _previousOffset) / _previousZoom;
    Offset newOffset = d.focalPoint / _scale - normalizedOffset * _zoom;

    setState(() {
      _zoom = newZoom;
      _offset = newOffset;
    });
  }

to this:

// Ensure that item under the focal point stays in the same place despite zooming
    final Offset normalizedOffset =
        (_startingFocalPoint - _previousOffset) / _previousZoom;
    Offset newOffset = d.focalPoint / _scale - normalizedOffset * _zoom;

    // Out of Bounds X]
    double give = 20.0;
    if (newOffset.dx > give/_scale) 
        newOffset = newOffset.scale(0.0, 1.0).translate(give/_scale, 0.0);  
    else if (newOffset.dx*_scale + size.width*_zoom < size.width - give)
        newOffset = newOffset.scale(0.0, 1.0).translate((size.width - size.width*_zoom - give)/_scale, 0.0);

    setState(() {
      _zoom = newZoom;
      _offset = newOffset;
    });
  }

Here the variable "give" is the padding around the picture when it moves to its extreme right or left. Feel free to incorporate this into your code. No attribution or anything necessary. Sorry I couldn't do any fancy animations, but maybe you can figure it out.

perlatus commented 7 years ago

If you've already got it in git, I'll merge whatever you send my way. Looks like this is a partial fix for #7. I can rework stuff after it's merged.