title: SwiftUI - how to override nested offset/position animations?
body: <p>Consider this simple example:</p>
  <pre><code>struct TestView: View {
      @State private var enabled = false
      
      var body: some View {
          Circle()
              .foregroundColor(.red)
              .overlay(
                  Circle()
                      .foregroundColor(.blue)
                      .frame(width: 50, height: 50)
                      .animation(.spring())
                  
              )
              .frame(width: 100, height: 100)
              .offset(x: 0, y: enabled ? -50 : 50)
              .animation(.easeIn(duration: 1.0))
              .onTapGesture{
                  enabled.toggle()
              }
              
      }
  }
  </code></pre>
  <p>This yields the following animation when tapping on the resulting circle:</p>
  <p><a href="https://i.stack.imgur.com/LBUfi.gif" rel="noreferrer"><img src="https://i.stack.imgur.com/LBUfi.gif" alt="enter image description here" /></a></p>
  <p>The nested circle animates to its new global position with its own timing function (spring), while the outer circle / parent view animates to the new global position with its easeInOut timing function. Ideally, all children would animate with the parents timing function if a modifier works at the parent views level of abstraction (in this case, <code>offset</code>, but also things like <code>position</code>).</p>
  <p>Presumably this happens because the SwiftUI rendering engine computes new global properties for all affected children in the view hierarchy in a layout pass, and animates changes to each property based on the most specific animation modifier attached (even though, in this case, the relative position of the child within the parent does not change). And this makes it incredibly hard to do something as simple as translate a view properly when subviews of that view might have their own complex animations running (which the parent view doesn't and really <em>shouldn't</em> know of).</p>
  <p>One other quirk I noticed is that, in this particular example, adding an <code>animation(nil)</code> modifier immediately <em>before</em> the offset modifier breaks the animations on the outer circle, despite the <code>.easeInOut</code> remaining attached directly to the offset modifier. This violates my understanding of how these modifiers are chained, where (according to <a href="https://www.hackingwithswift.com/books/ios-swiftui/controlling-the-animation-stack" rel="noreferrer">this source</a>) an animation modifier applies to all views it entails until the next nested animation modifier.</p>