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

如何在Maui.Graphics中绘制图像的局部区域

在MAUI GraphicsView中绘制图像局部区域的两种可行方案

方案一:利用画布裁剪(ClipRectangle)实现

通过限制画布的绘制区域,仅让目标局部图像内容显示在容器中,无需提前修改原图:

修改你的Draw方法:

public void Draw(ICanvas canvas, RectF containerRect)
{
    if (image != null)
    {
        // 保留你原有的DisplayedRect计算逻辑
        // Computes scaled size which is the size of the part of the image to be displayed
        double scaledWidth = image.Width / Scale;
        double scaledHeight = image.Height / Scale;

        // Computes horizontal coordinates
        double xCenterImageOUT = Center.X * image.Width;
        double xLeft = Math.Max(0, xCenterImageOUT - scaledWidth/2);
        double xRight = Math.Min(xCenterImageOUT + scaledWidth / 2, image.Width);
        if (xRight - xLeft < scaledWidth)
        {
            if (xLeft == 0) xRight = scaledWidth;
            else xLeft = image.Width - scaledWidth;
        }

        // Computes vertical coordinates
        double yCenterImageOUT = Center.Y * image.Height;
        double yTop = Math.Max(0, yCenterImageOUT - scaledHeight / 2);
        double yBottom = Math.Min(yCenterImageOUT + scaledHeight / 2, image.Height);
        if (yBottom - yTop < scaledHeight)
        {
            if (yTop == 0) yBottom = scaledHeight;
            else yBottom = image.Height - scaledHeight;
        }
        DisplayedRect = new Rect(xLeft, yTop, scaledWidth, scaledHeight);

        // --- 核心裁剪绘制逻辑 ---
        canvas.SaveState();
        // 设置裁剪区域为容器范围,超出部分不会被绘制
        canvas.ClipRectangle(containerRect);

        // 计算图像偏移量:让目标局部区域对齐容器左上角
        float offsetX = (float)(containerRect.X - DisplayedRect.X);
        float offsetY = (float)(containerRect.Y - DisplayedRect.Y);

        // 按原图尺寸绘制,偏移后仅裁剪区域内的内容会显示
        canvas.DrawImage(image, offsetX, offsetY, (float)image.Width, (float)image.Height);

        canvas.RestoreState();
    }
}

方案二:先裁剪出局部图像再绘制

如果需要重复使用同一局部图像,可提前将原图裁剪为新的IImage,再直接绘制到容器:

新增裁剪方法并修改Draw逻辑:

private IImage CropImage(IImage source, Rect sourceRect)
{
    // 创建与裁剪区域尺寸一致的新图像
    var croppedImage = new GraphicsImage((float)sourceRect.Width, (float)sourceRect.Height);
    using (var canvas = croppedImage.Canvas)
    {
        // 将原图的目标区域绘制到新图像的原点位置
        canvas.DrawImage(source, 
                        (float)-sourceRect.X, 
                        (float)-sourceRect.Y, 
                        (float)source.Width, 
                        (float)source.Height);
    }
    return croppedImage;
}

public void Draw(ICanvas canvas, RectF containerRect)
{
    if (image != null)
    {
        // 保留原有的DisplayedRect计算逻辑(同上)
        DisplayedRect = new Rect(xLeft, yTop, scaledWidth, scaledHeight);

        // --- 先裁剪再绘制 ---
        var croppedImage = CropImage(image, DisplayedRect);
        canvas.DrawImage(croppedImage, containerRect.X, containerRect.Y, containerRect.Width, containerRect.Height);
    }
}

方案对比

  • 方案一适合单次绘制场景,性能开销更低,无需额外创建图像对象
  • 方案二更适合需要重复复用局部图像的场景,避免每次绘制都计算偏移和裁剪

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 21:58:33