Erik
Erik

Reputation: 519

How to flip Shape horizontally in SwiftUI?

I have a Shape that need to be flipped along the x-axis. I'm looking for a way to solve this with CGAffineTransform, but I've only found a way to rotate the Shape, but not flipping along an axis. I need something like .rotation3DEffect(.degrees(180), axis: (x: 1, y: 0, z: 0))for Shapes

Upvotes: 1

Views: 8637

Answers (2)

Paul B
Paul B

Reputation: 5115

Here is way to get back a Shape (some Shape, I would say):

extension Shape {  
    func flipped() -> ScaledShape<Self> {
        scale(x: -1, y: 1, anchor: .center)
    }
}

If some more complex path manipulation is needed:

struct FlippedShape<Content>: Shape where Content : Shape {
    let content: Content
    func path(in rect: CGRect) -> Path {
        let flip = CGAffineTransform(scaleX: -1, y: 1)
        let position = flip.concatenating(CGAffineTransform(translationX: rect.width, y: 0))
        // some other path manipulation requiring `rect`
        return content.path(in: rect).applying(position)
    }
}

extension Shape {
    func flipped() -> FlippedShape<Self> {
        FlippedShape(content: self)
    }
}

Upvotes: 5

jnpdx
jnpdx

Reputation: 52407

You can use the rotation3DEffect on a shape. Here's a simple example:

struct ContentView : View {
    @State var degrees : Double = 0
    
    var body: some View {
        VStack {
            MyShape()
                .fill(Color.red)
                .rotation3DEffect(.degrees(degrees), axis: (x: 1, y: 0, z: 0))
            Button("Rotate") {
                withAnimation {
                    degrees = degrees == 0 ? 180 : 0
                }
            }
        }
    }
}

struct MyShape : Shape {
    func path(in rect: CGRect) -> Path {
        Path { path in
            path.move(to: .zero)
            path.addLine(to: CGPoint(x: rect.maxX, y: rect.minY))
            path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
        }
    }
}

Just to avoid confusion, I would say that your question title and your example of rotation3DEffect code and your title (flip shape "horizontally") conflict a little in my mind -- rotating 180 degrees with axis(x:1, y:0, z:0) performs what I would consider a vertical flip. For horizontal, you can change it to axis(x:0, y:1, z:0)

Upvotes: 11

Related Questions