Swift中绕指定中心旋转后在UIImage绘制矩形的问题排查
问题:绕指定中心旋转绘制矩形时位置偏移
需求是在UIImage上绕指定中心绘制旋转后的矩形,当前0度时显示正常,但旋转后矩形位置出现偏移。原思路是手动计算旋转后的矩形起始坐标再绘制,但存在错误。
原代码
func drawRotatedRectangleOnImage(image: UIImage, angle: Angle) -> UIImage? { let size = image.size UIGraphicsBeginImageContextWithOptions(size, false, 1.0) guard let context = UIGraphicsGetCurrentContext() else { return nil } let point = convertedPointOfRectangle(sizeOfFgImage: size) let rect = CGSize(500, 500) context.rotate(by: angle.radians) context.setFillColor(UIColor.gray.cgColor) context.fill(CGRect(x: point.x, y: point.y, width: rect.width, height: rect.height)) let newImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return newImage } func convertedPointOfRectangle(sizeOfFgImage : CGSize, angle: Angle) -> CGPoint { let size = DripContainerViewSize let point = CGPoint(0, 0) // starting point of the rectangle let center = CGPoint(x: 300, y: 300) // center for rotation let res = rotatePoint(center: center, point: CGPoint(x: pointX, y: pointY), angle: angle.radians) return res // after rotation, the position of the starting point } func rotatePoint(center: CGPoint, point: CGPoint, angle: Double) -> CGPoint { let x = (point.x - center.x) * cos(angle) + (point.y - center.y) * sin(angle) + center.x let y = (point.y - center.y) * cos(angle) - (point.x - center.x) * sin(angle) + center.y return CGPoint(x: x, y: y) }
错误分析
- 重复旋转操作:同时手动计算旋转后的坐标+旋转context,相当于对矩形做了两次旋转变换,导致位置偏移。
- 函数参数缺失:调用
convertedPointOfRectangle时未传入angle参数,且函数内部使用未定义的pointX/pointY变量,存在编译错误。 - 旋转中心处理错误:直接旋转context时,默认绕坐标系原点旋转,而非指定的(300,300)中心。
- 未绘制原图:原代码只绘制了矩形,最终输出图片会丢失原UIImage内容。
解决方案
利用Core Graphics的坐标变换链实现绕指定中心旋转,无需手动计算旋转点,步骤为:平移到旋转中心→旋转坐标系→平移回原位置,再绘制矩形。修正后的代码如下:
func drawRotatedRectangleOnImage(image: UIImage, angle: Angle) -> UIImage? { let size = image.size UIGraphicsBeginImageContextWithOptions(size, false, 1.0) guard let context = UIGraphicsGetCurrentContext() else { return nil } // 先绘制原始图片 image.draw(at: .zero) let rectSize = CGSize(width: 500, height: 500) let rotationCenter = CGPoint(x: 300, y: 300) // 自定义旋转中心 // 让矩形中心与旋转中心对齐,计算矩形起始点 let rectOrigin = CGPoint(x: rotationCenter.x - rectSize.width/2, y: rotationCenter.y - rectSize.height/2) // 坐标变换:平移到旋转中心 → 旋转 → 平移回原点,实现绕指定中心旋转 context.translateBy(x: rotationCenter.x, y: rotationCenter.y) context.rotate(by: angle.radians) context.translateBy(x: -rotationCenter.x, y: -rotationCenter.y) context.setFillColor(UIColor.gray.withAlphaComponent(0.5).cgColor) context.fill(CGRect(origin: rectOrigin, size: rectSize)) let newImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return newImage }
关键说明
- Core Graphics的变换是累积的,通过两次平移+旋转的组合,让后续绘制的内容绕指定中心旋转,避免手动计算坐标的误差。
- 若需要保持矩形的起始点(而非中心)对齐旋转中心,只需调整
rectOrigin的计算方式,比如直接用原始起始点即可。
内容的提问来源于stack exchange,提问作者Jabed Dhali
相关产品推荐
相关产品推荐

