Reputation: 519
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
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
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