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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 02:12:23