You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Maui应用实现自然Pinch to Zoom效果技术求助

图片捏合缩放(Pinch to Zoom)操作手感优化求助

我已为图片实现捏合缩放功能,但操作手感生硬、不够自然,尤其是结合平移操作时。由于我的方案需用单触摸完成绘图,无法将捏合(Pinch)与平移(Pan)容器结合使用。我尝试调整微软提供的各类Pinch Container示例,始终无法达到iOS相册应用的流畅效果。我已创建示例应用仓库。

实现代码

C# 捏合容器类

public class PinchContainer : ContentView
{
    private double currentScale = 1;
    private double startScale = 1;
    private double xOffset;
    private double yOffset;

    public PinchContainer()
    {
        var pinchGesture = new PinchGestureRecognizer();
        pinchGesture.PinchUpdated += OnPinchUpdated;
        
        GestureRecognizers.Add(pinchGesture);
    }

    private void OnPinchUpdated(object? sender, PinchGestureUpdatedEventArgs e)
    {
        if (e.Status == GestureStatus.Started)
        {
            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.
            var renderedX = Content.X + xOffset;
            var deltaX = renderedX / Width;
            var deltaWidth = Width / (Content.Width * startScale);
            var originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;

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

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

            // Apply translation based on the change in origin.
            Content.TranslationX = Math.Clamp(targetX, -Content.Width * (currentScale - 1), 0);
            Content.TranslationY = Math.Clamp(targetY, -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;
        }
    }
}

XAML 页面代码

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:pinchZoom="using:PinchZoom"
             x:Class="PinchZoom.MainPage"
             x:Name="View">

    <Grid
        HorizontalOptions="Fill"
        VerticalOptions="Fill"
        BindingContext="{Binding Source={x:Reference Name=View}}">

        <pinchZoom:PinchContainer
            IsClippedToBounds="True"
            HorizontalOptions="Center"
            VerticalOptions="Center"
            AbsoluteLayout.LayoutBounds="0,0,1,1"
            AbsoluteLayout.LayoutFlags="All">

            <Image
                Source="xp.jpg"
                Aspect="AspectFit"
                SemanticProperties.Description="dot net bot in a race car number eight" />

        </pinchZoom:PinchContainer>

    </Grid>

</ContentPage>

内容的提问来源于stack exchange,提问作者Austin Oberholtzer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 02:07:30