我想在我的应用程序中添加一个捏缩放功能。我有多个图像在网格中一个放在另一个之上,所以我使用了我在这里得到的这段代码:http: //mobile.dzone.com/articles/correcting-pinch-飞涨
<Grid x:Name="ContentPanel" Grid.Row="0" RenderTransformOrigin="0,0" >
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener
PinchStarted="OnPinchStarted"
PinchDelta="OnPinchDelta"
DragDelta="OnDragDelta"
DoubleTap="OnDoubleTap"/>
</toolkit:GestureService.GestureListener>
<Grid.RenderTransform>
<CompositeTransform
ScaleX="1" ScaleY="1"
TranslateX="0" TranslateY="0"/>
</Grid.RenderTransform>
<Grid.Children>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Height="800">
<Grid>
<Grid.Children>
<Image Source="sample1.png" />
<Image Source="sample1.png" />
<Image Source="sample1.png" />
<Image Source="sample1.png" />
<Image Source="sample1.png" />
<Image Source="sample1.png" />
<Image Source="sample1.png" />
<Image Source="sample1.png" />
<Image Source="sample1.png" />
<Image Source="sample1.png"/>
<Image Source="sample1.png" />
</Grid.Children>
</Grid>
</ScrollViewer>
</Grid.Children>
</Grid>
但问题是它不能平滑缩放。当我开始缩放时它需要一些时间然后响应。而当我尝试只使用一个图像时它工作正常。有没有办法让网格中的多个图像平滑缩放。
这些是我的事件处理程序:
private double TotalImageScale = 1d;
private Point ImagePosition = new Point(0, 0);
private const double MAX_IMAGE_ZOOM = 2.3;
private Point _oldFinger1;
private Point _oldFinger2;
private double _oldScaleFactor;
#region Event handlers
/// <summary>
/// Initializes the zooming operation
/// </summary>
private void OnPinchStarted(object sender, PinchStartedGestureEventArgs e)
{
_oldFinger1 = e.GetPosition(ContentPanel, 0);
_oldFinger2 = e.GetPosition(ContentPanel, 1);
_oldScaleFactor = 1;
}
/// <summary>
/// Computes the scaling and translation to correctly zoom around your fingers.
/// </summary>
private void OnPinchDelta(object sender, PinchGestureEventArgs e)
{
var scaleFactor = e.DistanceRatio / _oldScaleFactor;
if (!IsScaleValid(scaleFactor))
return;
var currentFinger1 = e.GetPosition(ContentPanel, 0);
var currentFinger2 = e.GetPosition(ContentPanel, 1);
var translationDelta = GetTranslationDelta(
currentFinger1,
currentFinger2,
_oldFinger1,
_oldFinger2,
ImagePosition,
scaleFactor);
_oldFinger1 = currentFinger1;
_oldFinger2 = currentFinger2;
_oldScaleFactor = e.DistanceRatio;
UpdateImageScale(scaleFactor);
UpdateImagePosition(translationDelta);
}
/// <summary>
/// Moves the image around following your finger.
/// </summary>
private void OnDragDelta(object sender, DragDeltaGestureEventArgs e)
{
var translationDelta = new Point(e.HorizontalChange, e.VerticalChange);
if (IsDragValid(1, translationDelta))
UpdateImagePosition(translationDelta);
}
/// <summary>
/// Resets the image scaling and position
/// </summary>
private void OnDoubleTap(object sender, Microsoft.Phone.Controls.GestureEventArgs e)
{
ResetImagePosition();
}
#endregion
#region Utils
/// <summary>
/// Computes the translation needed to keep the image centered between your fingers.
/// </summary>
private Point GetTranslationDelta(
Point currentFinger1, Point currentFinger2,
Point oldFinger1, Point oldFinger2,
Point currentPosition, double scaleFactor)
{
var newPos1 = new Point(
currentFinger1.X + (currentPosition.X - oldFinger1.X) * scaleFactor,
currentFinger1.Y + (currentPosition.Y - oldFinger1.Y) * scaleFactor);
var newPos2 = new Point(
currentFinger2.X + (currentPosition.X - oldFinger2.X) * scaleFactor,
currentFinger2.Y + (currentPosition.Y - oldFinger2.Y) * scaleFactor);
var newPos = new Point(
(newPos1.X + newPos2.X) / 2,
(newPos1.Y + newPos2.Y) / 2);
return new Point(
newPos.X - currentPosition.X,
newPos.Y - currentPosition.Y);
}
/// <summary>
/// Updates the scaling factor by multiplying the delta.
/// </summary>
private void UpdateImageScale(double scaleFactor)
{
TotalImageScale *= scaleFactor;
ApplyScale();
}
/// <summary>
/// Applies the computed scale to the image control.
/// </summary>
private void ApplyScale()
{
((CompositeTransform)ContentPanel.RenderTransform).ScaleX = TotalImageScale;
((CompositeTransform)ContentPanel.RenderTransform).ScaleY = TotalImageScale;
}
/// <summary>
/// Updates the image position by applying the delta.
/// Checks that the image does not leave empty space around its edges.
/// </summary>
private void UpdateImagePosition(Point delta)
{
var newPosition = new Point(ImagePosition.X + delta.X, ImagePosition.Y + delta.Y);
if (newPosition.X > 0) newPosition.X = 0;
if (newPosition.Y > 0) newPosition.Y = 0;
if ((ContentPanel.ActualWidth * TotalImageScale) + newPosition.X < ContentPanel.ActualWidth)
newPosition.X = ContentPanel.ActualWidth - (ContentPanel.ActualWidth * TotalImageScale);
if ((ContentPanel.ActualHeight * TotalImageScale) + newPosition.Y < ContentPanel.ActualHeight)
newPosition.Y = ContentPanel.ActualHeight - (ContentPanel.ActualHeight * TotalImageScale);
ImagePosition = newPosition;
ApplyPosition();
}
/// <summary>
/// Applies the computed position to the image control.
/// </summary>
private void ApplyPosition()
{
((CompositeTransform)ContentPanel.RenderTransform).TranslateX = ImagePosition.X;
((CompositeTransform)ContentPanel.RenderTransform).TranslateY = ImagePosition.Y;
}
/// <summary>
/// Resets the zoom to its original scale and position
/// </summary>
private void ResetImagePosition()
{
TotalImageScale = 1;
ImagePosition = new Point(0, 0);
ApplyScale();
ApplyPosition();
}
/// <summary>
/// Checks that dragging by the given amount won't result in empty space around the image
/// </summary>
private bool IsDragValid(double scaleDelta, Point translateDelta)
{
if (ImagePosition.X + translateDelta.X > 0 || ImagePosition.Y + translateDelta.Y > 0)
return false;
if ((ContentPanel.ActualWidth * TotalImageScale * scaleDelta) + (ImagePosition.X + translateDelta.X) < ContentPanel.ActualWidth)
return false;
if ((ContentPanel.ActualHeight * TotalImageScale * scaleDelta) + (ImagePosition.Y + translateDelta.Y) < ContentPanel.ActualHeight)
return false;
return true;
}
/// <summary>
/// Tells if the scaling is inside the desired range
/// </summary>
private bool IsScaleValid(double scaleDelta)
{
return (TotalImageScale * scaleDelta >= 1) && (TotalImageScale * scaleDelta <= MAX_IMAGE_ZOOM);
}
#endregion