wieslawsoltes / PanAndZoom

Pan and zoom control for Avalonia.
http://wieslawsoltes.github.io/PanAndZoom/
MIT License
345 stars 45 forks source link

Bug when MaxZoom or MinZoom are set #64

Closed izaksuilov closed 9 months ago

izaksuilov commented 2 years ago

If you set MaxZoom and try to zoom in it will scroll somewhere. Obviously if you try to zoom in when it is already a maximum zoom, nothing should change. It is the same thing with MinZoom.

In the example below MaxZoomX="1.4" MaxZoomY="1.4" MinZoomX="0.8" MinZoomY="0.8":

ZoomError

My suggestion is to replace the following code in file Avalonia.Controls.PanAndZoom.ZoomBorder at line 427

public void ZoomTo(double ratio, double x, double y, bool skipTransitions = false)
{
    if (_updating)
    {
        return;
    }
    _updating = true;
    ...
}

with this code

public void ZoomTo(double ratio, double x, double y, bool skipTransitions = false)
{
    if (_updating)
        return;
    if (EnableConstrains)
    {
        if (ZoomX >= MaxZoomX || ZoomY >= MaxZoomY)
        {
            if (ratio > 1)
                return;
        }
        if (ZoomX <= MinZoomX || ZoomY <= MinZoomY)
        {
            if (ratio < 1)
                return;
        }
    }
    _updating = true;
   ...
}

I also suggest to add e.KeyModifiers. In that case you zoom only if, for example, control is pressed. I suggest this because when you wheel without control pressed you not only zoom but scroll also. If you separate this things and add e.Handled = true, you can scroll and zoom separately on wheel. A also recommend to make fields ILogicalScrollable.ScrollSize and ILogicalScrollable.PageScrollSize editable, so you can customize the scrolling behavior.

I suggest to to replace the following code in file Avalonia.Controls.PanAndZoom.ZoomBorder at line 186

private void Wheel(PointerWheelEventArgs e)
{
     if (_element == null || _captured)
     {
         return;
     }
     var point = e.GetPosition(_element);
     ZoomDeltaTo(e.Delta.Y, point.X, point.Y);
}

with this code

private void Wheel(PointerWheelEventArgs e)
{
    if (_element == null || _captured)
        return;
    if (e.KeyModifiers != KeyModifiers.Control && e.KeyModifiers != KeyModifiers.Meta)
        return;

    var point = e.GetPosition(_element);
    ZoomDeltaTo(e.Delta.Y, point.X, point.Y);

    e.Handled = true;
}
izaksuilov commented 1 year ago

36