SwiftUI : Is there a way to force a Shape to rotate with the phone?

Viewed 65

SwiftUI : Is there a way to force a Shape (a View of type "Shape") to rotate with the phone (as opposed to rotate automatically) so that it keeps its original orientation with respect to the screen of the phone?


// Symbol House
struct House: Shape {
    
    let dx: CGFloat
    let dy: CGFloat
 
    func path(in r: CGRect) -> Path {
                
        var path = Path()
        
        var p0 = point(in: r, from: CGPoint(x: r.minX, y: r.minY))
        p0 = shift(p: p0, dx: dx, dy: dy)
        
        var  p1 = point(in: r, from: CGPoint(x: r.minX,  y: r.maxY/2))
        p1 = shift(p: p1, dx: dx, dy: dy)

        var p2 = point(in: r, from: CGPoint(x: r.maxX/2 , y: r.maxY))
        p2 = shift(p: p2, dx: dx, dy: dy)

        var p3 = point(in: r, from: CGPoint(x: r.maxX,  y: r.maxY/2))
        p3 = shift(p: p3, dx: dx, dy: dy)

        var p4 = point(in: r, from: CGPoint(x: r.maxX, y: r.minY))
        p4 = shift(p: p4, dx: dx, dy: dy)
        
        path.move(to: p0)
        path.addLine(to: p1)
        path.addLine(to: p2)
        path.addLine(to: p3)
        path.addLine(to: p4)
        path.addLine(to: p0)
        
        return path
    }
}
1 Answers

First, you need the current orientation...

struct DeviceRotationViewModifier: ViewModifier {
    let action: (UIDeviceOrientation) -> Void

func body(content: Content) -> some View {
    content
        .onAppear()
        .onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
            action(UIDevice.current.orientation)
        }
    }
}

extension View {
    func onRotate(perform action: @escaping (UIDeviceOrientation) -> Void) -> some View {
        self.modifier(DeviceRotationViewModifier(action: action))
    }
}

Now we can use the .rotationEffect() - modifier.

rotationEffect(_:anchor:) Rotates this view’s rendered output around the specified point. https://developer.apple.com/documentation/swiftui/view/rotationeffect(_:anchor:)

The apple example:

Text("Rotation by passing an angle in degrees")
    .rotationEffect(.degrees(22))
    .border(Color.gray)

enter image description here

...
@State private var orientation = UIDeviceOrientation.unknown
...
var body: some View {
    Group {
        if orientation.isPortrait{
            Shape().rotationEffect(.degrees(0))
        } else if orientation.isLandscape{
            Shape().rotationEffect(.degrees(90))
        }
    }.onRotate{ newOrientation in 
    orientation = newOrientation
    }
}

For more rotation features take a look at the link above, there are more rotation and transformation topics :-)

Related