Swift中Apple Map的MKOverlayRenderer图片缩放旋转异常求助
解决Apple Map叠加图片缩放超过2.0时旋转导致的损坏问题
问题出在坐标变换顺序错误以及旋转原点未设置为图片中心,当缩放级别较高时,CGContext的坐标映射会出现偏差,导致图片绘制超出上下文可视区域或像素错位,最终表现为图片损坏。
修复步骤
- 先保存当前上下文状态,避免后续变换影响其他绘制操作
- 将上下文平移至图片中心位置,确保旋转围绕图片中心进行
- 执行旋转操作后平移回原位置,修正坐标系
- 处理UIKit与Core Graphics的Y轴方向差异
- 绘制图片时确保上下文缩放因子与图片匹配
修改后的完整代码
class IndoorInfoOverlay: NSObject, MKOverlay { let coordinate: CLLocationCoordinate2D let boundingMapRect: MKMapRect init(indoorInfo: IndoorInfo) { boundingMapRect = indoorInfo.overlayBoundingMapRect coordinate = indoorInfo.midCoordinate } } class IndoorInfoOverlayView: MKOverlayRenderer { var overlayImage: UIImage var parent: IndoorMapView init(overlay: MKOverlay, overlayImage: UIImage, _ parent: IndoorMapView) { self.overlayImage = overlayImage self.parent = parent super.init(overlay: overlay) } override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) { guard let imageReference = overlayImage.cgImage else { return } let bearing = degreesToRadians(360 - (Double(self.parent.floorData?.FLOOR_BEARING ?? 0))) let rect = self.rect(for: overlay.boundingMapRect) // 保存上下文初始状态 context.saveGState() // 平移到图片中心,围绕中心旋转后再平移回原位置 let center = CGPoint(x: rect.midX, y: rect.midY) context.translateBy(x: center.x, y: center.y) context.rotate(by: CGFloat(bearing)) context.translateBy(x: -center.x, y: -center.y) // 处理UIKit与Core Graphics的Y轴翻转 context.scaleBy(x: 1.0, y: -1.0) context.translateBy(x: 0.0, y: -rect.size.height) // 绘制图片 let imageRect = CGRect(origin: .zero, size: rect.size) context.draw(imageReference, in: imageRect, byTiling: false) // 恢复上下文状态 context.restoreGState() } private func degreesToRadians(_ x: Double) -> Double { return Double.pi * x / 180.0 } }
关键说明
- 旋转原点修正:通过先平移到图片中心再旋转,避免旋转后图片位置偏移,确保高缩放级别下图片始终在正确的地图区域内
- 上下文状态隔离:用
saveGState()和restoreGState()隔离当前绘制的变换操作,不会干扰地图其他元素的渲染 - 坐标系逻辑调整:重新安排变换顺序,先处理旋转再处理Y轴翻转,保证坐标计算逻辑正确,避免像素错位
内容的提问来源于stack exchange,提问作者user2805987
相关产品推荐
相关产品推荐

