SwiftUI拖动视图后基于当前偏移中心旋转的实现问题
解决SwiftUI视图拖动后绕当前中心旋转的问题
问题核心:你当前的代码中,offset仅做视觉偏移,不会改变视图的布局原点,导致rotationEffect始终以初始布局中心为旋转轴。要让旋转中心跟随视图当前位置,可通过以下两种方案修正:
方案一:使用变换矩阵合并平移与旋转(推荐)
通过CGAffineTransform将平移和旋转合并为一个变换,所有操作基于视图自身坐标系,旋转中心始终是当前视图的几何中心:
struct MyGestureView: View { // 存储累积的平移+旋转变换 @State private var transform = CGAffineTransform.identity var body: some View { Rectangle() .frame(width: 100, height: 100) .transformEffect(transform) .gesture( DragGesture(minimumDistance: 0) .onChanged { value in // 基于上次变换累积平移量 transform = transform.translatedBy(x: value.translation.width, y: value.translation.height) } ) .gesture( RotationGesture(minimumAngleDelta: .degrees(3)) .onChanged { angle in // 绕当前视图中心旋转 transform = transform.rotated(by: angle.radians) } ) } }
方案二:用position替代offset调整视图位置
position会改变视图的布局原点,此时rotationEffect的旋转中心会自动跟随视图的当前位置:
struct MyGestureView: View { @State private var lastOffset: CGPoint = .zero @State private var currentOffset: CGPoint = .zero @State private var lastRotation: Angle = .zero @State private var currentRotation: Angle = .zero var body: some View { Rectangle() .frame(width: 100, height: 100) .rotationEffect(currentRotation) .position(currentOffset) .gesture( DragGesture(minimumDistance: 0) .onChanged { value in currentOffset = CGPoint( x: lastOffset.x + value.translation.width, y: lastOffset.y + value.translation.height ) } .onEnded { _ in lastOffset = currentOffset } ) .gesture( RotationGesture(minimumAngleDelta: .degrees(3)) .onChanged { angle in currentRotation = lastRotation + angle } .onEnded { _ in lastRotation = currentRotation } ) .onAppear { // 初始化视图位置为屏幕中心 currentOffset = CGPoint(x: UIScreen.main.bounds.midX, y: UIScreen.main.bounds.midY) lastOffset = currentOffset } } }
关键说明
- 方案一逻辑更简洁,所有变换操作基于视图自身坐标系,无需额外管理位置状态。
- 方案二通过修改布局位置实现需求,适合需要单独管理平移、旋转状态的场景。
内容的提问来源于stack exchange,提问作者Jabed Dhali
相关产品推荐
相关产品推荐

