0

我想在我的应用程序中添加一个捏缩放功能。我有多个图像在网格中一个放在另一个之上,所以我使用了我在这里得到的这段代码: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
4

2 回答 2

1

我得到了解决方案。我忘记将 CacheMode="BitmapCache" 写入调用手势事件的网格。它现在按预期工作。

于 2013-09-17T10:55:30.283 回答
0

您是否尝试过用视图框包围您的网格?视图框可以很好地缩放其内容。通常,视图框与滚动输入一起使用。但我认为它也适用于 Windows 手机上的触摸手势。

让我知道它是否有效;)

于 2013-09-17T07:48:09.160 回答