如何用AffineTransform围绕视图中心旋转CGPoint?UIBezierPath旋转可行但方案失效
围绕视图中心旋转CGPoint的可行方案
我太懂研究一上午没进展的憋屈感了!你说的网格旋转方案不适用,核心原因是没处理UIKit坐标系和旋转原点的差异——网格旋转一般默认以(0,0)为原点,但你需要的是围绕视图的中心旋转,得先做坐标转换才行。下面给你一套直接能用的步骤和代码:
核心三步法
1. 将目标点转换为「以视图中心为原点」的相对坐标
UIKit视图的坐标系原点在左上角,所以首先要把目标点的坐标减去视图中心的坐标,把原点“移”到视图中心:
// 先获取视图的中心坐标(基于自身bounds) let viewCenter = CGPoint(x: yourView.bounds.midX, y: yourView.bounds.midY) // 计算目标点相对于视图中心的位置 let pointRelativeToCenter = CGPoint( x: targetPoint.x - viewCenter.x, y: targetPoint.y - viewCenter.y )
2. 应用2D旋转公式计算旋转后的相对坐标
用标准的旋转公式,注意UIKit的Y轴是向下的,所以旋转方向是顺时针(如果需要逆时针,给角度传负数即可)。这里的角度要传弧度制(比如CGFloat.pi是180度,CGFloat.pi/2是90度):
let rotationAngle: CGFloat = .pi/2 // 示例:旋转90度 let rotatedX = pointRelativeToCenter.x * cos(rotationAngle) - pointRelativeToCenter.y * sin(rotationAngle) let rotatedY = pointRelativeToCenter.x * sin(rotationAngle) + pointRelativeToCenter.y * cos(rotationAngle) let rotatedRelativePoint = CGPoint(x: rotatedX, y: rotatedY)
3. 转换回视图坐标系
把旋转后的相对坐标加回视图中心坐标,就得到了最终在视图里的旋转后点:
let finalRotatedPoint = CGPoint( x: rotatedRelativePoint.x + viewCenter.x, y: rotatedRelativePoint.y + viewCenter.y )
封装成工具方法(推荐复用)
把上面的逻辑封装成CGPoint的扩展,以后用起来超方便:
extension CGPoint { /// 围绕指定中心点旋转当前点 /// - Parameters: /// - center: 旋转中心点 /// - angle: 旋转角度(弧度制,顺时针为正) /// - Returns: 旋转后的点 func rotated(around center: CGPoint, by angle: CGFloat) -> CGPoint { let dx = x - center.x let dy = y - center.y let rotatedX = dx * cos(angle) - dy * sin(angle) let rotatedY = dx * sin(angle) + dy * cos(angle) return CGPoint(x: rotatedX + center.x, y: rotatedY + center.y) } }
使用示例
// 假设你有一个目标点和要旋转的视图 let targetPoint = CGPoint(x: 30, y: 30) let yourView = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200)) let viewCenter = CGPoint(x: yourView.bounds.midX, y: yourView.bounds.midY) // 旋转90度 let rotatedPoint = targetPoint.rotated(around: viewCenter, by: .pi/2)
为什么之前的网格方案不适用?
那些网格旋转方案一般默认旋转原点是坐标系的(0,0),但你的需求是围绕视图中心——这个中心在视图坐标系里是(midX, midY),不是(0,0),所以必须先做坐标平移,把目标点转到以中心为原点的坐标系里再旋转,转完再平移回去,这是关键的差异点。
内容的提问来源于stack exchange,提问作者digit
相关产品推荐
相关产品推荐

