SwiftUi覆盖视图停止动画

guicsvcw  于 5个月前  发布在  Swift
关注(0)|答案(1)|浏览(51)

我有一个内置在swift中的相机,我想让用户将相机聚焦在某个点上。当用户点击屏幕上的任何地方时,我想显示一个动画视图,代表一个焦点动作。这个视图功能正常,但点击屏幕上的多个不同的点后,视图停止动画,并冻结在相机上方。我尝试使用调度队列,所以视图总是消失后,但这并不起作用。

struct HomeStory: View {
    @State var focusLocation: (CGFloat, CGFloat)?
    
    var body: some View {
        ZStack(alignment: .bottom) {
            CameraStoryView()
                .onTapGesture { tapP in
                    UIImpactFeedbackGenerator(style: .light).impactOccurred()
                    focusLocation = (tapP.x, tapP.y)
                    cameraModel.focus(at: CGPoint(x: tapP.x, y: tapP.y))
                }

            let w = widthOrHeight(width: true)
            let h = widthOrHeight(width: false)
            if let points = focusLocation, (points.0 > 20) && (points.0 < w - 20) && (points.1 > 80) && (points.1 < h - (h * 0.3)) {
                FocusView()
                    .position(x: points.0, y: points.1 - 35)
                    .onAppear {
                        let p1 = points.0
                        DispatchQueue.main.asyncAfter(deadline: .now() + 0.75) {
                            if (focusLocation?.0 ?? 0.0) == p1 {
                                focusLocation = nil
                            }
                        }
                    }
                    .offset(y: 35)
            }
     }
}
struct FocusView: View {
    @State var animate = false
    var body: some View {
        ZStack {
            Circle()
                .fill(.white.opacity(0.75))
                .frame(width: 70, height: 70)
                .scaleEffect(self.animate ? 1 : 0)
                .opacity(animate ? 0 : 1)
            
            Circle()
                .fill(.white)
                .frame(width: 7, height: 4)
                .scaleEffect(self.animate ? 7.0 : 1)
                .opacity(animate ? 0.3 : 1)
        }
        .onAppear {
            DispatchQueue.main.async {
                self.animate = true
            }
        }
        .onDisappear {
            DispatchQueue.main.async {
                self.animate = false
            }
        }
        .animation(.linear(duration: 0.7), value: animate)
    }
}

字符串

f5emj3cl

f5emj3cl1#

如果在focusLocation设置为nil之前设置了一个新位置,则HomeStory View中的onAppear可能不会触发。您的动画也不会从头开始(它是同一个FocusView,并且其animate状态已设置为true)。
假设你一次只想显示一个FocusView,你可以使用一个.id视图修改器耦合到位置。这将确保你的动画为每个新位置重置。类似这样:

struct FocusLocation {
    let x: CGFloat
    let y: CGFloat
    
    // create unique id for every new location
    let id = UUID()
}

struct HomeStory: View {
    @State var focusLocation: FocusLocation?
    
    var body: some View {
        ZStack(alignment: .bottom) {
            Color.blue
                .onTapGesture { tapP in
                    // new location with a new id
                    focusLocation = FocusLocation(x: tapP.x, y: tapP.y)
                }
            
            if let focusLocation {
                FocusView()
                    .position(x: focusLocation.x, y: focusLocation.y)
                    .task {
                        do {
                            try await Task.sleep(for: .milliseconds(750))
                            self.focusLocation = nil
                        } catch {
                            // the task is cancelled
                            // (the view has been replaced)
                        }
                    }
                    // new id means a new View
                    .id(focusLocation.id)
            }
        }
    }
}
    
struct FocusView: View {
    @State var animate = false
    
    var body: some View {
        ZStack {
            Circle()
                .fill(.white.opacity(0.75))
                .frame(width: 70, height: 70)
                .scaleEffect(self.animate ? 1 : 0)
                .opacity(animate ? 0 : 1)
            
            Circle()
                .fill(.white)
                .frame(width: 7, height: 4)
                .scaleEffect(self.animate ? 7.0 : 1)
                .opacity(animate ? 0.3 : 1)
        }
        .onAppear { animate = true }
        .animation(.linear(duration: 0.7), value: animate)
    }
}

字符串

相关问题