Flincorp
Flincorp

Reputation: 941

How can i rotate an image in SwiftUI with one finger only?

I have an image in a view and i want to be able to rotate it with one finger only, how can i do that in SwiftUI?

I checked the RotationGesture but it works only with two fingers...

Thanks

Upvotes: 2

Views: 2089

Answers (5)

Julie
Julie

Reputation: 11

Using the solutions from above this is what I have for rotating with one finger. This will keep the position when you finish rotating as well as starting the next rotation where the last one left off.

struct SwiftUIView: View {
    
    @State private var rotation: Angle = Angle(degrees: 0)
    @State private var previousRotation: Angle?
    

    var body: some View {
      
            Circle()
                .fill(AngularGradient(gradient: Gradient(colors: [Color.red, Color.blue]), center: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/, angle: .degrees(90)))
                .frame(width: 760, height: 760)
                .rotationEffect(rotation, anchor: .center)
                .gesture(DragGesture()
                    .onChanged{ value in
                        if let previousRotation = self.previousRotation {
                            let deltaY = value.location.y - (760 / 2)
                            let deltaX = value.location.x - (760 / 2)
                            let fingerAngle = Angle(radians: Double(atan2(deltaY, deltaX)))
                            
                            let angle = fingerAngle - previousRotation
                            rotation += angle
                            self.previousRotation = fingerAngle
                            
                        } else {
                            let deltaY = value.location.y - (760 / 2)
                            let deltaX = value.location.x - (760 / 2)
                            let fingerAngle = Angle(radians: Double(atan2(deltaY, deltaX)))
                            previousRotation = fingerAngle
                        }
                    }
                    .onEnded{ _ in
                        previousRotation = nil
                    })

    }
}

Upvotes: 1

Vipul Dungranee_MI
Vipul Dungranee_MI

Reputation: 27

A dragGesture will give us the value of a location where user has dragged on screen (in our case, the circle). Here, the circle frame will be equal height and equal width.

Capturing the location point where the user tapped and subtracting height/2 from y point and width/2 from x point results in deltaX and deltaY. Once we have deltaX and deltaY, we can convert it into radians using the atan2 function (which is provided by the Swift Standard Library).

struct SwiftUIView: View {
    
    @State var angle: Angle = .zero
    var circleFrame: CGRect = CGRect(x: 0, y: 0, width: 300, height: 300)

    var body: some View {
        Circle()
            .fill(AngularGradient(gradient: Gradient(colors: [Color.red, Color.blue]), center: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/, angle: .degrees(90)))
            .padding()
            .rotationEffect(angle)
            .gesture(
                DragGesture()
                    .onChanged { value in
                        let deltaY = value.location.y - (circleFrame.height / 2)
                        let deltaX = value.location.x - (circleFrame.width / 2)
                        angle = Angle(radians: Double(atan2(deltaY, deltaX)))  
                    }
            )
    }
}

Upvotes: 0

Flincorp
Flincorp

Reputation: 941

Ok, i got it with this code :
https://gist.github.com/ts95/9f8e05380824c6ca999ab3bc1ff8541f

Upvotes: 4

Flincorp
Flincorp

Reputation: 941

Ok fixed it with this code :

struct RotationGesture: View {
    @State var totalRotation = CGSize.zero
    @State var currentRotation = CGSize.zero
    
    var body: some View {
        Text("Hello, World!")
            .frame(width: 150, height: 60)
            .padding()
            .background(Color.orange)
            .cornerRadius(15)
            .rotationEffect(Angle(degrees: Double(-totalRotation.width)))
            .gesture(
                DragGesture()
                    .onChanged { value in
                        totalRotation.width = value.translation.width + currentRotation.width
                    }
                    .onEnded { value in
                        currentRotation = totalRotation
                    }
            )
    }
}

But now we have to fixed the vertical movement because this solution is only working when you move around the X axis...

I want to solution to work when you make circle movement around the view you want to rotate...

Upvotes: 1

Ufuk Köşker
Ufuk Köşker

Reputation: 1480

one finger rotation

struct RotationGesture: View {
        @State var gestureValue = CGSize.zero
        var body: some View {
            Text("Hello, World!")
                .frame(width: 150, height: 60)
                .padding()
                .background(Color.orange)
                .cornerRadius(15)
                .rotationEffect(Angle(degrees: Double(-gestureValue.width)))
                .gesture(
                    DragGesture().onChanged({ (value) in
                        self.gestureValue = value.translation
                    }).onEnded({ (value) in
                        self.gestureValue = .zero
                    })
                )
                .animation(.spring(response: 0.5, dampingFraction: 0.6, blendDuration: 0))
        }
    }

Upvotes: 0

Related Questions