如何旋转平移缩放MKOverlay图片叠加层使其与地图区域匹配?
问题根源
- 旋转锚点错误:
CGContext默认围绕当前坐标系原点旋转,当前实现直接在左上角原点执行旋转,必然会出现位置偏移,旋转的锚点应该是图片叠加层的中心。 ImageOverlay的coordinate属性赋值错误:MKMapRect的midX/midY是墨卡托投影的平面坐标,不能直接当做经纬度赋值给CLLocationCoordinate2D,会导致叠加层基础定位偏差。- 坐标变换顺序错误:Core Graphics的变换是按书写顺序反向作用于绘制内容,需调整变换的执行顺序适配旋转逻辑。
代码修改方案
1. 修正ImageOverlay初始化方法的坐标赋值
init(image: UIImage, boundingMapRect: MKMapRect, rotation: CLLocationDirection) { self.image = UIImage.fixedOrientation(for: image) ?? image self.boundingMapRect = boundingMapRect // 修正:将墨卡托坐标转换为经纬度 let centerPoint = MKMapPoint(x: boundingMapRect.midX, y: boundingMapRect.midY) self.coordinate = MKCoordinateForMapPoint(centerPoint) self.rotation = rotation }
2. 修正叠加层渲染的旋转逻辑
override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) { guard let overlay = overlay as? ImageOverlay else { return } let rect = self.rect(for: overlay.boundingMapRect) let imageCenter = CGPoint(x: rect.midX, y: rect.midY) // 适配Core Graphics与UIKit的Y轴坐标差异 context.scaleBy(x: 1.0, y: -1.0) context.translateBy(x: 0, y: -rect.maxY) // 平移坐标系到图片中心作为旋转锚点 context.translateBy(x: imageCenter.x, y: imageCenter.y) // 执行旋转(若旋转方向与地图航向相反可添加负号调整) context.rotate(by: CGFloat(overlay.rotation * Double.pi / 180)) // 平移坐标系回图片左上角 context.translateBy(x: -rect.width / 2, y: -rect.height / 2) // 绘制图片 context.draw(overlay.image.cgImage!, in: CGRect(origin: .zero, size: rect.size)) }
额外说明
如果测试后发现图片旋转方向和地图航向不匹配,只需将旋转角度的计算添加负号即可:context.rotate(by: -CGFloat(overlay.rotation * Double.pi / 180)),这是Y轴翻转后旋转方向默认反向导致的。
内容的提问来源于stack exchange,提问作者vrwim
相关产品推荐
相关产品推荐

