CodeCopy

December 15, 2011

WP7 Pinch and Pan Zoom an Image

Filed under: c# — mazzoo @ 14:56

Here’s how to implement Pinch to Zoom and Pan on an Image Control – using the WP7 toolkit. ( Thanks to Alvaro Peon for this great solution  )

Remember allways to add CacheMode=”BitmapCache” to you Image for performance Open-mouthed smile

XAML:


<Image HorizontalAlignment="Left" Name="photo" Stretch="Uniform" VerticalAlignment="Top" Source="Image.png" CacheMode="BitmapCache">
<Image.RenderTransform>
<CompositeTransform x:Name="ImageTransformation" ScaleX="1" ScaleY="1" />
</Image.RenderTransform>
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener PinchStarted="GestureListener_PinchStarted" PinchDelta="OnPinchDelta" DragDelta="Image_DragDelta" />
</toolkit:GestureService.GestureListener>
</Image>

C# Codebehind:


private Point Center;
private double InitialScale;

private void GestureListener_PinchStarted(object sender, PinchStartedGestureEventArgs e)
{
// Store the initial rotation angle and scaling
InitialScale = ImageTransformation.ScaleX;
// Calculate the center for the zooming
Point firstTouch = e.GetPosition(Image_LargeImage, 0);
Point secondTouch = e.GetPosition(Image_LargeImage, 1);

Center = new Point(firstTouch.X + (secondTouch.X - firstTouch.X) / 2.0, firstTouch.Y + (secondTouch.Y - firstTouch.Y) / 2.0);
}

private void OnPinchDelta(object sender, PinchGestureEventArgs e)
{
// If its less that the original  size or more than 4x then don’t apply
if (InitialScale * e.DistanceRatio > 4 || (InitialScale != 1 && e.DistanceRatio == 1) || InitialScale * e.DistanceRatio < 1)
return;

// If its original size then center it back
if (e.DistanceRatio <= 1.08)
{
ImageTransformation.CenterY = 0;
ImageTransformation.CenterY = 0;
ImageTransformation.TranslateX = 0;
ImageTransformation.TranslateY = 0;
}

ImageTransformation.CenterX = Center.X;
ImageTransformation.CenterY = Center.Y;

// Update the rotation and scaling
if (this.Orientation == PageOrientation.Landscape)
{
// When in landscape we need to zoom faster, if not it looks choppy
ImageTransformation.ScaleX = InitialScale * (1 + (e.DistanceRatio - 1) * 2);
}
else
{
ImageTransformation.ScaleX = InitialScale * e.DistanceRatio;
}
ImageTransformation.ScaleY = ImageTransformation.ScaleX;
}

private void Image_DragDelta(object sender, DragDeltaGestureEventArgs e)
{
// if is not touch enabled or the scale is different than 1 then don’t allow moving
if (ImageTransformation.ScaleX <= 1.1)
return;

double centerX = ImageTransformation.CenterX;
double centerY = ImageTransformation.CenterY;
double translateX = ImageTransformation.TranslateX;
double translateY = ImageTransformation.TranslateY;
double scale = ImageTransformation.ScaleX;
double width = Image_LargeImage.ActualWidth;
double height = Image_LargeImage.ActualHeight;

// Verify limits to not allow the image to get out of area
if (centerX - scale * centerX + translateX + e.HorizontalChange < 0 && centerX + scale * (width - centerX) + translateX + e.HorizontalChange > width)
{
ImageTransformation.TranslateX += e.HorizontalChange;
}

if (centerY - scale * centerY + translateY + e.VerticalChange < 0 && centerY + scale * (height - centerY) + translateY + e.VerticalChange > height)
{
ImageTransformation.TranslateY += e.VerticalChange;
}

return;
}

Advertisement

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Theme: Rubric. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.