首页 > 解决方案 > 如何在执行新动画时保持初始动画运行?

问题描述

我很难弄清楚这个动画的事情。问题是, .onAppear 摇晃动画(应该永远循环)在视图被拖动后立即停止并冻结(它有另一个动画,以便它平滑地移动到拖动位置)。

有没有办法让 onAppear 动画独立于被拖动的视图运行?需要注意的重要一点是,我确实需要依赖于数组的位置(因此拖动手势直接写入数据),并且我根本不需要将摆动(大小动画)绑定到数组。

动画在拖动时冻结的插图(不受欢迎 - 想要在被拖动期间和之后转圈以仍然摆动)

界

请看代码:

   var body: some View {
        
      
            
       
        
        Circle()
           
          //  .resizable()
            .frame(width:size.width, height: size.height) //self.size is a state var
            .foregroundColor(color)
            .position(pos) //pos is a normal var bound to an array row
            .gesture(DragGesture()
            
                        .onChanged { gesture in
                        
                         withAnimation(.default) {
                            ballStorage.balls[numberInArray].position = gesture.location
                            }
                            
                            
                        }
                        .onEnded { gesture in
                          
                             ballStorage.checkOverlaps(for: numberInArray)
                           
                        }
                        
            ) .onAppear {
                
                withAnimation(Animation.easeInOut(duration: 1).repeatForever(autoreverses: true)) {
                    
                    size = CGSize(width: size.width+20, height: size.height+20)
                }
                
            }

        }
}

标签: swiftxcodeanimationswiftui

解决方案


您需要用自己的动画将圆圈分成自己的视图,然后内部动画将独立于外部动画。

这是关于以某种方式复制的代码的解决方案演示。使用 Xcode 12.1 / iOS 14.1 准备。

演示

struct Ball: Identifiable, Hashable {
    let id = UUID()
    var position = CGPoint.zero
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(id)
    }
}

struct BallView: View {
    let ball: Ball
    var color = Color.blue
    @State private var size = CGSize(width: 40, height: 40)
    var body: some View {
        Circle()
            .frame(width:size.width, height: size.height) //self.size is a state var
            .animation(Animation.easeInOut(duration: 1).repeatForever(autoreverses: true), value: size)
            .foregroundColor(color)
            .onAppear {
                size = CGSize(width: size.width+20, height: size.height+20)
            }
    }
}

struct ContentView: View {
    @State private var balls = [Ball(position: CGPoint(x: 100, y: 100)), Ball(position: CGPoint(x: 100, y: 200))]
    @State private var off = CGSize.zero
    @State private var selected = -1
    var body: some View {
        
        ZStack {
            ForEach (Array(balls.enumerated()), id: \.1) { i, ball in
                BallView(ball: ball)
                    .offset(x: i == selected ? off.width : 0, y: i == selected ? off.height : 0)
                    .position(ball.position)
                    .gesture(DragGesture()
                        .onChanged { gesture in
                            self.selected = i
                            withAnimation(.default) {
                                self.off = gesture.translation
                            }
                        }
                        .onEnded { gesture in
                                let pt = balls[i].position
                                self.balls[i].position = CGPoint(x: pt.x + gesture.translation.width, y: pt.y + gesture.translation.height)
                                self.off = .zero
                                self.selected = -1
//                          ballStorage.checkOverlaps(for: numberInArray)
                        }
                    )
            }
        }
    }
}

推荐阅读