'SwiftUI rotation animation has unexpected translation [duplicate]

I'm trying to animate a spinning "busy" image in a SwiftUI View using standard and consistent online tutorials. The image is square, should be scaled uniformly, and spin forever.

I can get a spinning image with the following code, however I am seeing unexpected translations with this. When used in a NavigationView as the initial View the image moves over the course of the animation from top-left to the center of the screen. When used as the third screen in a NavigationView the image starts roughly in the center of the screen and moves vertically downwards by about half its height over the course of the animation. Removing the navigationBar and back button reduce the vertical shift to about 20px overall. Which is interesting.

Also interestingly, the background stays exactly where I'd expect it to be, in the center of the screen in both cases. autoreverses behaves as expected and anchoring the rotation effect seems to have no effect.

The aim is to have additional controls on the screen (text, Next button etc) but for now I'd be happy with an animation that stays in one place.

What am I doing wrong? Any help appreciated!

Image illustrating the problemThe code:

@State private var isAnimating = false

var body: some View {
    VStack{
        Spacer()
        Image("FilmCircle")
            .resizable()
            .scaledToFit()
            .frame(width: 100, height: 100)
            .rotationEffect(Angle(degrees: isAnimating ? 360 : 0), anchor: .center)
            .animation(Animation.linear(duration: 2)
                .repeatForever(autoreverses: false))
            .onAppear {
                self.isAnimating = true
            }
            .background(Color.red)
        Spacer()
    }
}


Solution 1:[1]

Declare .backgound(Color.red) before declaring animation so that it will animate background as well.

And for issue when using navigation view, see the code : -

    VStack{
    Spacer()
    Image("FilmCircle")
        .resizable()
        .scaledToFit()
        .background(Color.red)
        .frame(width: 100, height: 100)
        .rotationEffect(Angle(degrees: isAnimating ? 360 : 0), anchor: .center)
        .onAppear {
             DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
                           withAnimation(.linear(duration: 2).repeatForever(autoreverses: false)) {
                               isAnimating = true
                           }
                       }
        }
        Spacer()
    }

Hope you found this helpful.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1