使用UITouch绘制矩形后截图裁剪位置错误,求正确实现方案
屏幕绘制矩形后截图裁剪位置不正确的问题解决
问题描述
通过UITouch在屏幕绘制矩形并记录坐标,截取全屏截图后按记录的坐标裁剪,结果裁剪位置始终与绘制的矩形不匹配。
核心原因
- 坐标系统不匹配:屏幕触摸坐标基于「点(Point)」,而UIImage的CGImage是像素级数据。Retina屏幕下,1个点对应2或3个像素,直接用点坐标裁剪像素级图像会导致位置、尺寸缩放错误。
- 旧版截图代码存在兼容性问题:原代码遍历
UIApplication.shared.windows的方式在iOS13+已失效,且窗口变换处理可能引入额外坐标偏移。
解决方案
1. 修正裁剪坐标的像素转换
将记录的点坐标乘以截图的scale值,转换为像素坐标后再裁剪:
func cropImage(screenshot: UIImage) -> UIImage { let scale = screenshot.scale // 把点坐标转为像素坐标 let cropRect = CGRect( x: xCurrent * scale, y: yCurrent * scale, width: widthCurrent * scale, height: heightCurrent * scale ) guard let cgImage = screenshot.cgImage?.cropping(to: cropRect) else { return screenshot // 裁剪失败返回原图 } // 保留原图的scale和方向,避免图片变形 return UIImage(cgImage: cgImage, scale: scale, orientation: screenshot.imageOrientation) }
2. 适配iOS13+的全屏截图代码
改用场景(Scene)获取主窗口,避免旧版API的兼容性问题:
@IBAction func createScreenshot(_ sender: Any) { // 获取当前活跃的主窗口 guard let window = UIApplication.shared.connectedScenes .filter({$0.activationState == .foregroundActive}) .compactMap({$0 as? UIWindowScene}) .first?.windows .first(where: {$0.isKeyWindow}) else { return } let imageSize = window.bounds.size // 用屏幕scale创建上下文,保证截图清晰度 UIGraphicsBeginImageContextWithOptions(imageSize, false, UIScreen.main.scale) window.drawHierarchy(in: window.bounds, afterScreenUpdates: true) let screenshot = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() if let screenshot = screenshot { let croppedImage = cropImage(screenshot: screenshot) // 后续处理裁剪后的图片(保存/展示等) } }
3. 确保绘制坐标的准确性
如果触摸事件在子视图中处理,需将视图内坐标转换为全局窗口坐标:
// 示例:在UIView的触摸方法中转换坐标 override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { guard let touch = touches.first else { return } // 将视图本地坐标转为窗口全局坐标 let windowPoint = touch.location(in: self.window) // 调用绘制方法时传入转换后的坐标 drawSelectionArea(fromPoint: 起始点, toPoint: windowPoint) }
内容的提问来源于stack exchange,提问作者Redstain
相关产品推荐
相关产品推荐

