SwiftUI | 动画路径形状

4

我有以下情况:

我想使用自定义动画翻转此形状。我不知道如何准确描述它。

每次我点击箭头时,它应该变换成另一个箭头。不需要翻转、旋转等,只需简单的变换即可。

如果这不够精确,请随意评论!

演示代码

struct ContentView: View {
    
    @State private var change = false
    
    private let arrowWidth: CGFloat = 80
    
    
    var body: some View {
        Path { path in
            path.move(to: .zero)
            path.addLine(to: CGPoint(x: arrowWidth/2, y: change ? -20 : 20))
            path.move(to: CGPoint(x: arrowWidth/2, y: change ? -20 : 20))
            path.addLine(to: CGPoint(x: arrowWidth, y: 0))
        }
        .stroke(style: StrokeStyle(lineWidth: 12, lineCap: .round))
        .frame(width: arrowWidth)
        .foregroundColor(.green)
        .animation(.default)
        .onTapGesture { change.toggle() }
        .padding(.top, 300)
    }
}

你现在可以看到它没有动画。我不知道该如何做。

任何帮助都将不胜感激。谢谢!

注意:我不能用两个圆角矩形+简单旋转来做这件事,因为我有一个透明度动画,这会使重叠可见。

1个回答

8

这里有一个可能的方法-将路径移入自定义形状,并将已更改的参数作为可动画属性。

更新:在Xcode 13.3 / iOS 15.4下重新测试

演示

struct MyArrow: Shape {
    var width: CGFloat
    var offset: CGFloat
    
    var animatableData: CGFloat {
        get { offset }
        set { offset = newValue }
    }
    
    func path(in rect: CGRect) -> Path {
        Path { path in
            path.move(to: .zero)
            path.addLine(to: CGPoint(x: width/2, y: offset))
            path.move(to: CGPoint(x: width/2, y: offset))
            path.addLine(to: CGPoint(x: width, y: 0))
        }
    }
}

struct ContentView: View {
    
    @State private var change = false
    
    private let arrowWidth: CGFloat = 80
    
    
    var body: some View {
        MyArrow(width: arrowWidth, offset: change ? -20 : 20)
        .stroke(style: StrokeStyle(lineWidth: 12, lineCap: .round))
        .frame(width: arrowWidth)
        .foregroundColor(.green)
        .contentShape(Rectangle())
        .onTapGesture { withAnimation { change.toggle() } }
        .onTapGesture { change.toggle() }
        .padding(.top, 300)
    }
}

1
很棒的答案。(已投票。)我几乎没有接触过SwiftUI。我知道如何使用CAAnimation和CAShapeLayer来完成这个任务,但不理解这种方法是如何工作的。你能否详细解释一下它的工作原理? - Duncan C
2
@DuncanC,当状态改变时,SwiftUI渲染引擎会检测到修改的MyArrow视图,并且由于它是可动画的,使用当前上下文动画的设置从旧值插值到新值来绘制它的animatableData。您可以在https://swiftui-lab.com/category/animations找到详细的好文章。 - Asperi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接