Search code examples
swiftswiftuiviewrotationdrag

Rotation applied centering its previous offset after dragging in SwiftUI


I want to make a view in swiftUI such that I can drag view as well as rotate the view based on its current offset. But unfortunately after translating the view, when I try to rotate, it rotates centering its base offset, not current center of the view. I am now looking for a precised solution such that the view will rotate from its current center. My code is here for better understanding:

struct MyGestureView : View {
    
    @State private var lastOffset : CGSize = .zero
    @State private var offset : CGSize = .zero
    
    @State private var lastRotation : Angle = .zero
    @State private var rotation : Angle = .zero
    
    var body: some View {
        Rectangle()
            .frame(width: 100, height: 100)
            .offset(offset)
            .rotationEffect(rotation)
            .gesture(
                DragGesture(minimumDistance: 0)
                    .onChanged({ value in
                        offset.width = lastOffset.width + value.translation.width
                        offset.height = lastOffset.height + value.translation.height
                    })
                    .onEnded({ value in
                        lastOffset = offset
                    })
            )
            .gesture(
                RotationGesture(minimumAngleDelta: Angle.degrees(3))
                    .onChanged({ angle in
                        rotation = lastRotation + angle
                    })
                    .onEnded({ angle in
                        lastRotation = rotation
                    })
            )
    }
}

Solution

  • Rotate the view first, without adding any offsets, so that the view is rotated correctly. Then you can add offsets, which does not affect the rotation.

    i.e. switch the order of rotationEffect and offset:

    .rotationEffect(rotation)
    .offset(offset)