How to make to limit the image dragging area in app?

721 Views Asked by At

Now, I'm developing photo application(windows phone 8.1 runtime) but I got the problem is that did not to limit the image dragging area while the photos is zooming.

enter image description here

Here below is code:

<Canvas Name="zoomgrid" Visibility="Collapsed">
    <Image x:Name="zoomimages"
           Stretch="Fill"
           Width="480"
           Height="800"
           ManipulationDelta="img_intro_ManipulationDelta"
           RenderTransformOrigin="0.5,0.5"
           ManipulationMode="All">
        <Image.RenderTransform>
            <CompositeTransform/>
        </Image.RenderTransform>                
    </Image>
</Canvas>

double mincale = 0.5;
double maxscale = 10.0;

private void Image_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{           
    Image elemt = sender as Image;
    CompositeTransform transform = elemt.RenderTransform as CompositeTransform;

    transform.ScaleX *= e.Delta.Scale;
    transform.ScaleY *= e.Delta.Scale;

    transform.TranslateX += e.Delta.Translation.X;
    transform.TranslateY += e.Delta.Translation.Y;

    if (transform.ScaleX < mincale) transform.ScaleX = mincale;
    if (transform.ScaleY < mincale) transform.ScaleY = mincale;
    if (transform.ScaleX > maxscale) transform.ScaleX = maxscale;
    if (transform.ScaleY > maxscale) transform.ScaleY = maxscale;

    //To limit the images dragging but did not success.
    double scalewidth = Zoomimages.ActualWidth * ct.ScaleX;
    double scleheight = Zoomimages.ActualHeight * ct.ScaleY;

    double xdiff = Math.Max(0, (scalewidth - this.content.ActualWidth) / 2);
    double ydiff = Math.Max(0, (scleheight - this.content.ActualHeight) / 2);

    if (Math.Abs(ct.TranslateX) > xdiff)
        ct.TranslateX = xdiff * Math.Sign(e.Delta.Translation.X);
    if (Math.Abs(ct.TranslateY) > ydiff)
        ct.TranslateY = ydiff * Math.Sign(e.Delta.Translation.Y);             
}
1

There are 1 best solutions below

0
On

I've achieved the this by using a helper method to check whether the image is currently within the bounds of another element.

In your case, the element you'd want to check is the image, and you want to check it's within the bounds of the canvas.

private bool IsElementVisible(FrameworkElement element, FrameworkElement container)
    {
        if (!element.IsVisible)
            return false;

        Rect bounds = element.TransformToAncestor(container).TransformBounds(new Rect(0.0, 0.0, element.ActualWidth, element.ActualHeight));
        Rect rect = new Rect(0.0, 0.0, container.ActualWidth, container.ActualHeight);

        if (rect.Left > bounds.Right || rect.Right < bounds.Left || rect.Bottom < bounds.Top || rect.Top > bounds.Bottom)
        {
            return false;
        }

        return true;
    }

In my case, I've used a MatrixTransform instead of a CompositeTransform, but the method should be the same.

I usually create handlers for 'ManipulationStarting' and 'ManipulationCompleted', where:

ManipulationStarting:

  1. Stores the current (pre-manipulation) copy of the Transform.

ManipulationCompleted:

  1. Check to see if the image is out of bounds (using the method I've posted).
  2. If out of bounds, then revert to the original Transform.

This way, even if your image is dragged out of view - as soon as the user lifts their finger, the image will pop back to the last good location.

If you're interested the broader context in which I used this code, I have a WPF behaviour that encapsulates all this functionality. The code is on Codeplex. This class may be of interest to you.

I hope this helps :)