Search code examples
wpfxamlzoomingbehavior

WPFExtensions ZoomControl - Pinch zoom is jumping


I want to use the pinch gesture too zoom with the WPFExtensions.Controls.ZoomControl.

Based on this answer - i know how to detect the pinch gesture. I use it as member _detector. I use ZoomControl.ManipulationDelta to do the zoom.

So I thought i just take ManipulationDelta and Zoom like this:

private void AssociatedObject_ManipulationDelta(object sender, System.Windows.Input.ManipulationDeltaEventArgs e)
{
    if (_detector.IsScalingAllowed) // this just tells me if it is a pinch gesture or not
    {
        if ((e.DeltaManipulation.Scale.X < 1)
            || (e.DeltaManipulation.Scale.X > 1))
        {
            //AssociatedObject is ZoomControl
            AssociatedObject.Zoom = Math.Max(e.DeltaManipulation.Scale.X, e.DeltaManipulation.Scale.Y);
        }
    }
}

But this will just make my ZoomControl zoom pretty poor with for and back jumps.

My complete code looks like this:

public class ZoomBoxBehaviour : Behavior<ZoomControl>
{
    private GestureDetector _detector;

    protected override void OnAttached()
    {
        base.OnAttached();
        if (AssociatedObject != null)
        {
            _detector = new GestureDetector(AssociatedObject);

            if (!AssociatedObject.IsManipulationEnabled) AssociatedObject.IsManipulationEnabled = true;

            AssociatedObject.ManipulationDelta += AssociatedObject_ManipulationDelta;
        }
    }

    protected override void OnDetaching()
    {
        if (AssociatedObject != null)
        {
            AssociatedObject.ManipulationDelta -= AssociatedObject_ManipulationDelta;
        }

        base.OnDetaching();
    }

    private void AssociatedObject_ManipulationDelta(object sender, System.Windows.Input.ManipulationDeltaEventArgs e)
    {
        if (_detector.IsScalingAllowed) // this just tells me if it is a pinch gesture or not
        {
            if ((e.DeltaManipulation.Scale.X < 1)
                || (e.DeltaManipulation.Scale.X > 1))
            {
                AssociatedObject.Zoom = Math.Max(e.DeltaManipulation.Scale.X, e.DeltaManipulation.Scale.Y);
            }
        }
    }
}

You can get the GestureDetector here from the first answer.

UPDATE

I made it to zoom properly to the center

    private void AssociatedObject_ManipulationDelta(object sender, System.Windows.Input.ManipulationDeltaEventArgs e)
    {
        if (_detector.IsScalingAllowed) // this just tells me if it is a pinch gesture or not
        {
            if ((e.DeltaManipulation.Scale.X < 1)
                || (e.DeltaManipulation.Scale.X > 1))
            {
                AssociatedObject.Zoom = Math.Max(e.CumulativeManipulation.Scale.X, e.CumulativeManipulation.Scale.Y);

                //Size newSize = new Size(AssociatedObject.ZoomBox.Size.Width * e.CumulativeManipulation.Scale.X,
                //                        AssociatedObject.ZoomBox.Size.Height * e.CumulativeManipulation.Scale.Y);

                //AssociatedObject.ZoomTo(new Rect(new Point(0,0), newSize));
            }
        }


    }

But now i want to Zoom to the Center of my gesture, but this commented code will just zoom in to max .... Why?


Solution

  • I solved it

    public class ZoomBoxBehaviour : Behavior<ZoomControl>
        {
            private GestureDetector _detector;
            protected override void OnAttached()
            {
                base.OnAttached();
                if (AssociatedObject != null)
                {
                    _detector = new GestureDetector(AssociatedObject);
    
                    if (!AssociatedObject.IsManipulationEnabled) AssociatedObject.IsManipulationEnabled = true;
    
                    AssociatedObject.ManipulationDelta += AssociatedObject_ManipulationDelta;
                }
            }
    
    
            protected override void OnDetaching()
            {
                if (AssociatedObject != null)
                {
                    AssociatedObject.ManipulationDelta -= AssociatedObject_ManipulationDelta;
                }
    
                base.OnDetaching();
            }
    
            private void AssociatedObject_ManipulationStarting(object sender, ManipulationStartingEventArgs e)
            {
                e.ManipulationContainer = ((FrameworkElement)e.Source).Parent as FrameworkElement;
            }
    
            private void AssociatedObject_ManipulationDelta(object sender, System.Windows.Input.ManipulationDeltaEventArgs e)
            {
                if (_detector.IsPanningAllowed)
                {
    
                    // Limit the X/Y translation extent to prevent the element from 'jumping' when using slow touchscreens, or many touch points.
                    const double translationThreshold = 100.0;
    
                    //Perform a translation(pan) tranformation
                    if ((e.DeltaManipulation.Translation.X < translationThreshold &&
                         e.DeltaManipulation.Translation.X > -translationThreshold)
                    )
                    {
                        AssociatedObject.TranslateX += e.DeltaManipulation.Translation.X;
                    }
    
                    if ((e.DeltaManipulation.Translation.Y < translationThreshold &&
                         e.DeltaManipulation.Translation.Y > -translationThreshold))
                    {
                        AssociatedObject.TranslateY += e.DeltaManipulation.Translation.Y;
                    }
                }
    
                if (_detector.IsScalingAllowed) // this just tells me if it is a pinch gesture or not
                {
                    if ((e.CumulativeManipulation.Scale.X < 1)
                        || (e.CumulativeManipulation.Scale.X > 1))
                    {
                        AssociatedObject.Zoom = Math.Max(e.CumulativeManipulation.Scale.X, e.CumulativeManipulation.Scale.Y);
                    }
                }
    
            }
    
        }