如何在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
相关产品推荐
相关产品推荐

