Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 使用按钮触发的动画将停止在外观上添加的repeatForever动画_Swift_Animation_Swiftui - Fatal编程技术网

Swift 使用按钮触发的动画将停止在外观上添加的repeatForever动画

Swift 使用按钮触发的动画将停止在外观上添加的repeatForever动画,swift,animation,swiftui,Swift,Animation,Swiftui,我想建立一个进度视图,它看起来像一个随着进度的增加而充满水的圆圈 为此,我制作了一个自定义的形状,用于创建水,并添加了一个动画,在该形状上以波浪效果永久重复。 因此,我想在进度增加时添加一个动画,以模拟水位增加 问题是,当我触发最后一个动画时,它添加到屏幕上的动画停止工作。 有没有办法解决这一问题,使两个动画结合在一起,然后repeatfever一个动画永不停止? 以下是一个例子: 以下是完整的代码: struct WaterWaveView: View { @State var pr

我想建立一个进度视图,它看起来像一个随着进度的增加而充满水的圆圈

为此,我制作了一个自定义的
形状
,用于创建水,并添加了一个动画,在该
形状
上以波浪效果永久重复。 因此,我想在进度增加时添加一个动画,以模拟水位增加

问题是,当我触发最后一个动画时,它添加到屏幕上的动画停止工作。 有没有办法解决这一问题,使两个动画结合在一起,然后
repeatfever
一个动画永不停止? 以下是一个例子:

以下是完整的代码:

struct WaterWaveView: View {
    @State var progress: CGFloat = 0.1
    @State var phase: CGFloat = 0.5

    var body: some View {
        VStack {
            WaterWave(progress: self.progress, phase: self.phase)
                .fill(Color.blue)
                .clipShape(Circle())
                .frame(width: 250, height: 250)
                .onAppear {
                    withAnimation(Animation.linear(duration: 1)
                                    .repeatForever(autoreverses: false)) {
                        self.phase = .pi * 2
                    }
                }
            Button("Add") {
                withAnimation(.easeOut(duration: 1)) {
                    self.progress += 0.1
                }
            }
            Button("Reset") {
                self.progress = 0.0
            }
        }
    }
}

struct WaterWave: Shape {
    var progress: CGFloat
    let amplitude: CGFloat = 10
    let waveLength: CGFloat = 20
    var phase: CGFloat

    var animatableData: AnimatablePair<CGFloat, CGFloat> {
        get { AnimatablePair(phase, progress) }
        set {
            phase = newValue.first
            progress = newValue.second
        }
    }

    func path(in rect: CGRect) -> Path {
        var path = Path()

        let width = rect.width
        let height = rect.height
        let midWidth = width / 2
        let progressHeight = height * (1 - progress)

        path.move(to: CGPoint(x: 0, y: progressHeight))

        for x in stride(from: 0, to: width, by: 10) {
            let relativeX = x/waveLength
//            let normalizedLength = relativeX / midWidth

            let normalizedLength = (x - midWidth) / midWidth
            let y = progressHeight + sin(phase + relativeX) * amplitude * normalizedLength
            path.addLine(to: CGPoint(x: x, y: y))
        }

        path.addLine(to: CGPoint(x: width, y: progressHeight))
        path.addLine(to: CGPoint(x: width, y: height))
        path.addLine(to: CGPoint(x: 0, y: height))
        path.addLine(to: CGPoint(x: 0, y: progressHeight))

        return path
    }
}
struct WaterWaveView:View{
@状态变量进度:CGFloat=0.1
@状态变量相位:CGFloat=0.5
var body:一些观点{
VStack{
水波(进展:自我进展,阶段:自我阶段)
.填充(颜色.蓝色)
.clipShape(圆())
.框架(宽度:250,高度:250)
奥纳佩尔先生{
withAnimation(动画.线性)(持续时间:1)
.repeatForever(自动反转:false)){
self.phase=.pi*2
}
}
按钮(“添加”){
带动画(.easeOut(持续时间:1)){
self.progress+=0.1
}
}
按钮(“重置”){
self.progress=0.0
}
}
}
}
结构水波:形状{
var进度:CGFloat
let振幅:CGFloat=10
让波长:CGFloat=20
var相位:CGFloat
var animatableData:AnimatablePair{
获取{AnimatablePair(阶段,进度)}
设置{
阶段=newValue.first
进度=newValue.second
}
}
func路径(在rect:CGRect中)->path{
var path=path()
let width=rect.width
let height=rect.height
让中间宽度=宽度/2
让progressHeight=高度*(1-进度)
移动路径(到:CGPoint(x:0,y:progressHeight))
对于跨步x(从:0到:宽度,由:10){
设相对x=x/波长
//设normalizedLength=relativeX/middidth
设normalizedLength=(x-middidth)/middidth
设y=前进高度+正弦(相位+相对X)*振幅*归一化长度
path.addLine(到:CGPoint(x:x,y:y))
}
path.addLine(to:CGPoint(x:width,y:progressHeight))
path.addLine(to:CGPoint(x:width,y:height))
path.addLine(到:CGPoint(x:0,y:height))
addLine(to:CGPoint(x:0,y:progressHeight))
返回路径
}
}

至少目前(SwiftUI 2.0)未添加(累积)SwiftUI动画。所以这里有可能的解决方法

使用Xcode 12/iOS 14进行测试


这回答了你的问题吗?可能会有帮助。然后您可以执行
changevalueTowernath(值:self.$progress,newValue:self.progress+0.1,持续时间:1)
而不是调用
withAnimation{self.progress+=0.1}
@Asperi这在更改进度值时不使用动画,因此无法真正解决我的问题@vacawama Hm,它实际上不起作用,因为我的值在我的真实代码库中的
ViewModel
中被修改。谢谢,它起作用了,因为在我的真实最终用例中,值是从
ViewModel
修改的,我只是在
progress
var上用on
onChange
更改了我的
onAppear
,然后,我将示例中添加按钮操作的内容添加到这个
onChange
:)
struct WaterWaveView: View {
    @State var progress: CGFloat = 0.1
    @State var phase: CGFloat = 0.5

    var body: some View {
        VStack {
            WaterWave(progress: self.progress, phase: self.phase)
                .fill(Color.blue)
                .clipShape(Circle())
                .frame(width: 250, height: 250)
                .animation(phase == 0 ? .default : Animation.linear(duration: 1).repeatForever(autoreverses: false), value: phase)
                .animation(.easeOut(duration: 1), value: progress)
                .onAppear {
                            self.phase = .pi * 2
                }
            Button("Add") {
                    self.phase = 0
                    self.progress += 0.1
                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
                        self.phase = .pi * 2
                    }
            }
            Button("Reset") {
                self.progress = 0.0
            }
        }
    }
}