简体   繁体   中英

Zooming in windows phone apps

i want to put a pinch zooming functionality in my app.i have multiple images place one above the other in a grid so I used this code which I got here : http://mobile.dzone.com/articles/correcting-pinch-zoom

<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>

But the problem is it does not zoom smoothly.when I start zooming it takes some time and then responds.whereas when I tried with only one image it worked fine.is there any way to make zooming smooth with multiple images in a grid.

These are my event handlers:

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

我得到了解决方案。我忘了将CacheMode =“ BitmapCache”写入调用手势事件的网格。它现在按预期运行。

Have you tried to surround your grid with a viewbox? A viewbox allows to zoom its content quite good. Normally the viewbox works with scroll-input. But I think it will also work with touch-gestures on your windows phone.

Let me know if it works ;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM