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

如何在MAUI的SKCanvasView中通过鼠标滚轮实现图片缩放功能?

MAUI Windows平台SKCanvasView鼠标滚轮缩放实现方案

核心思路

通过MAUI的自定义控件处理程序(Handler),直接访问Windows平台上SKCanvasView对应的原生控件SKElement,绑定其PointerWheelChanged事件来实现滚轮缩放,无需调用底层Windows API。


实现步骤

1. 创建自定义SKCanvasView(可选但更清晰)

定义带滚轮事件的自定义控件,用于传递缩放增量:

public class CustomSKCanvasView : SKCanvasView
{
    public event EventHandler<double>? WheelScrolled;

    public void OnWheelScrolled(double scaleDelta)
    {
        WheelScrolled?.Invoke(this, scaleDelta);
    }
}

2. 编写Windows平台自定义处理程序

在项目Platforms/Windows目录下创建CustomSKCanvasViewHandler.cs,绑定原生控件的滚轮事件:

using Microsoft.Maui.Handlers;
using SkiaSharp.Views.Windows;

namespace YourAppNamespace.Platforms.Windows;

public class CustomSKCanvasViewHandler : SKCanvasViewHandler
{
    protected override void ConnectHandler(SKElement nativeView)
    {
        base.ConnectHandler(nativeView);
        nativeView.PointerWheelChanged += NativeView_PointerWheelChanged;
    }

    protected override void DisconnectHandler(SKElement nativeView)
    {
        nativeView.PointerWheelChanged -= NativeView_PointerWheelChanged;
        base.DisconnectHandler(nativeView);
    }

    private void NativeView_PointerWheelChanged(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
    {
        var wheelDelta = e.GetCurrentPoint(null).Properties.MouseWheelDelta;
        // 转换为缩放系数:滚轮向上放大10%,向下缩小10%
        var scaleDelta = wheelDelta > 0 ? 1.1 : 0.9;
        
        if (VirtualView is CustomSKCanvasView customView)
        {
            customView.OnWheelScrolled(scaleDelta);
        }
    }
}

3. 注册自定义处理程序

在MauiProgram.cs中配置平台专属处理程序:

builder.ConfigureMauiHandlers(handlers =>
{
#if WINDOWS
    handlers.AddHandler<CustomSKCanvasView, CustomSKCanvasViewHandler>();
#endif
});

4. 页面中实现缩放逻辑

在XAML中使用自定义控件:

<local:CustomSKCanvasView x:Name="canvasView" PaintSurface="CanvasView_PaintSurface" />

代码后台处理缩放与渲染:

private double _scale = 1.0;
private SKPoint _origin = SKPoint.Empty;
private SKPoint _currentMousePos = SKPoint.Empty;

public MainPage()
{
    InitializeComponent();
    canvasView.WheelScrolled += CanvasView_WheelScrolled;
    // 绑定鼠标移动事件,记录当前鼠标位置用于缩放中心点计算
    canvasView.PointerMoved += (s, e) =>
    {
        _currentMousePos = e.GetPosition(canvasView).ToSKPoint();
    };
}

private void CanvasView_WheelScrolled(object? sender, double scaleDelta)
{
    // 以当前鼠标位置为中心缩放,保持视觉焦点
    _origin = new SKPoint(
        _currentMousePos.X - (_currentMousePos.X - _origin.X) * scaleDelta,
        _currentMousePos.Y - (_currentMousePos.Y - _origin.Y) * scaleDelta
    );
    
    _scale *= scaleDelta;
    // 限制缩放范围,避免过度缩放
    _scale = Math.Clamp(_scale, 0.1, 10.0);
    
    canvasView.InvalidateSurface();
}

private void CanvasView_PaintSurface(object? sender, SKPaintSurfaceEventArgs e)
{
    var canvas = e.Surface.Canvas;
    canvas.Clear(SKColors.White);

    if (_targetImage != null) // _targetImage为你要显示的SKBitmap对象
    {
        canvas.Save();
        canvas.Translate(_origin.X, _origin.Y);
        canvas.Scale((float)_scale);
        canvas.DrawBitmap(_targetImage, 0, 0);
        canvas.Restore();
    }
}

关键说明

  • 无需直接调用Windows API,通过MAUI的Handler机制即可访问原生控件的事件。
  • 缩放中心点绑定鼠标位置,符合桌面端用户操作直觉。
  • 可根据需求调整缩放系数(如改为每滚轮一格缩放15%)或缩放范围限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 19:10:13