0

I have a view that is two halves of an Image, which I'm attempting to make a folding accordion style animation. As the viewed angle increases towards 90 degrees, the view should be increasingly closer to a height of 0.

struct HeroModuleView: View {
    @Binding var viewedAngle: Double
    
    @State private var offset = 0.0
    @State private var imageFrame: CGRect?
    
    var body: some View {
        ZStack {
            if let image = UIImage(named: "mountain-hero"),
               let topHalf = image.topHalf,
               let bottomHalf = image.bottomHalf {
                
                VStack(spacing: 0) {
                    Image(uiImage: topHalf)
                        .resizable()
                        .scaledToFill()
                        .rotation3DEffect(.degrees(-viewedAngle), axis: (x: 1.0, y: 0.0, z: 0.0), anchor: .top)
                        .offset(y: offset)
                        .clipped()
                        .getFrame(frame: $imageFrame)

                    Image(uiImage: bottomHalf)
                        .resizable()
                        .scaledToFill()
                        .rotation3DEffect(.degrees(viewedAngle), axis: (x: 1.0, y: 0.0, z: 0.0), anchor: .bottom)
                        .offset(y: -offset)
                        .clipped()
                }
                .brightness(-(viewedAngle / 90) * 0.2)
            }
        }
        .frame(maxHeight: 200)
        .onReceive(Just(viewedAngle)) { angle in
            self.offset = (angle / 90) * (imageFrame?.size.height ?? 0)
        }
    }
}

enter image description here

As you can see form the image, the frame, when the image is rotated in 3D space, begins to move towards the anchor point. I have tried adjusting things based on a .center anchor, however the offset doesn't do anything I expect it to and frankly I can't work out the math behind it. I attempted to use some sin calculations but those proved unfruitful. I need the frame of the ZStack to clip the height of both of these views after their effect has been applied, there should be no space above or below them.

xTwisteDx
  • 2,152
  • 1
  • 9
  • 25

0 Answers0