使用 PinchGestureRecognizer 缩放时图像闪烁

问题描述

我使用以下代码放置 <Image><Image.GestureRecognizers> 以实现缩放功能。 还提供了事件 PinchUpdated="PinchGestureRecognizer_PinchUpdated" 背后的代码。 缩放功能有效,但捏合时闪烁过多。

XAML:

            <Image 
                Grid.Column="0" 
                Grid.Row="0"
                x:Name="pageIterator"
                Grid.ColumnSpan="3">
                <Image.GestureRecognizers>
                    <PinchGestureRecognizer PinchUpdated="PinchGestureRecognizer_PinchUpdated"></PinchGestureRecognizer>
                </Image.GestureRecognizers>
            </Image>

背后的代码

        private void PinchGestureRecognizer_PinchUpdated(object sender,PinchGestureUpdatedEventArgs e)
        {
            double currentScale = 1;
            double startScale = 1;
            double xOffset = 0;
            double yOffset = 0;

            if (e.Status == GestureStatus.Started)
            {
                // Store the current scale factor applied to the wrapped user interface element,// and zero the components for the center point of the translate transform.
                startScale = Content.Scale;
                Content.AnchorX = 0;
                Content.AnchorY = 0;
            }
            if (e.Status == GestureStatus.Running)
            {
                // Calculate the scale factor to be applied.
                currentScale += (e.Scale - 1) * startScale;
                currentScale = Math.Max(1,currentScale);

                // The ScaleOrigin is in relative coordinates to the wrapped user interface element,// so get the X pixel coordinate.
                double renderedX = Content.X + xOffset;
                double deltaX = renderedX / Width;
                double deltaWidth = Width / (Content.Width * startScale);
                double originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;

                // The ScaleOrigin is in relative coordinates to the wrapped user interface element,// so get the Y pixel coordinate.
                double renderedY = Content.Y + yOffset;
                double deltaY = renderedY / Height;
                double deltaHeight = Height / (Content.Height * startScale);
                double originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;

                // Calculate the transformed element pixel coordinates.
                double targetX = xOffset - (originX * Content.Width) * (currentScale - startScale);
                double targetY = yOffset - (originY * Content.Height) * (currentScale - startScale);

                // Apply translation based on the change in origin.
                Content.TranslationX = targetX.Clamp(-Content.Width * (currentScale - 1),0);
                Content.TranslationY = targetY.Clamp(-Content.Height * (currentScale - 1),0);

                // Apply scale factor.
                Content.Scale = currentScale;
            }
            if (e.Status == GestureStatus.Completed)
            {
                // Store the translation delta's of the wrapped user interface element.
                xOffset = Content.TranslationX;
                yOffset = Content.TranslationY;
            }
        }


解决方法

您应该将以下几行移出 PinchGestureRecognizer_PinchUpdated 方法,否则您实际上每次触发时都会初始化这些值。

double currentScale = 1;
double startScale = 1;
double xOffset = 0;
double yOffset = 0;

private void PinchGestureRecognizer_PinchUpdated(object sender,PinchGestureUpdatedEventArgs e)
    {
        if (e.Status == GestureStatus.Started)
        {
            // Store the current scale factor applied to the wrapped user interface element,// and zero the components for the center point of the translate transform.
            startScale = Content.Scale;
            Content.AnchorX = 0;
            Content.AnchorY = 0;
        }
        if (e.Status == GestureStatus.Running)
        {
            // Calculate the scale factor to be applied.
            currentScale += (e.Scale - 1) * startScale;
            currentScale = Math.Max(1,currentScale);

            // The ScaleOrigin is in relative coordinates to the wrapped user interface element,// so get the X pixel coordinate.
            double renderedX = Content.X + xOffset;
            double deltaX = renderedX / Width;
            double deltaWidth = Width / (Content.Width * startScale);
            double originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;

            // The ScaleOrigin is in relative coordinates to the wrapped user interface element,// so get the Y pixel coordinate.
            double renderedY = Content.Y + yOffset;
            double deltaY = renderedY / Height;
            double deltaHeight = Height / (Content.Height * startScale);
            double originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;

            // Calculate the transformed element pixel coordinates.
            double targetX = xOffset - (originX * Content.Width) * (currentScale - startScale);
            double targetY = yOffset - (originY * Content.Height) * (currentScale - startScale);

            // Apply translation based on the change in origin.
            Content.TranslationX = targetX.Clamp(-Content.Width * (currentScale - 1),0);
            Content.TranslationY = targetY.Clamp(-Content.Height * (currentScale - 1),0);

            // Apply scale factor.
            Content.Scale = currentScale;
        }
        if (e.Status == GestureStatus.Completed)
        {
            // Store the translation delta's of the wrapped user interface element.
            xOffset = Content.TranslationX;
            yOffset = Content.TranslationY;
        }
    }