You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)
}

错误分析

  1. 重复旋转操作:同时手动计算旋转后的坐标+旋转context,相当于对矩形做了两次旋转变换,导致位置偏移。
  2. 函数参数缺失:调用convertedPointOfRectangle时未传入angle参数,且函数内部使用未定义的pointX/pointY变量,存在编译错误。
  3. 旋转中心处理错误:直接旋转context时,默认绕坐标系原点旋转,而非指定的(300,300)中心。
  4. 未绘制原图:原代码只绘制了矩形,最终输出图片会丢失原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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 19:12:04