SwiftUI - 动画路径形状描边绘图

2024-03-23

有没有一种方法可以在目标点发生变化时为路径的笔画绘制动画?

这是我的代码片段:

struct JourneyMapLineView: View {        
    @Binding var rects: [CGRect]

    var body: some View {
        rects.count != 0 ?
            JourneyMapLineShape(startRect: rects[0], endRect: rects[rects.count-1])
                .stroke(Color.red), lineWidth: 8)
                .animation(.easeInOut(duration: 0.3)) //<-- Is not working
        : nil
    }
}

struct JourneyMapLineShape: Shape {
    var startRect: CGRect
    var endRect: CGRect

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

        path.move(to: startRect.origin)
        path.addLine(to: endRect.origin)

        return path
    }
}

目前,如您所见,通过更改 的值没有动画endRect:

我已经看过一些类似的问题,看来这是一个新案例。

太感谢了!


更新:Xcode 13.4 / iOS 15.5

The .animation已弃用,因此更正的部分是

Route(points: self.vm.points, head: self.vm.lastPoint)
    .stroke(style: StrokeStyle(lineWidth: 8, lineCap: .round, lineJoin: .miter, miterLimit: 0, dash: [], dashPhase: 0))
    .foregroundColor(.red)
    .animation(.linear(duration: 0.5), value: self.vm.lastPoint) // << here !!

测试模块在这里 https://github.com/Asperi-Demo/4SwiftUI/blob/master/PlayOn_iOS/PlayOn_iOS/Findings/TestRoutePathStrokeAnimate.swift

Original

这是可能解决方案的演示。使用 Xcode 11.4 / iOS 13.4 进行测试

// Route shape animating head point
struct Route: Shape {
    var points: [CGPoint]
    var head: CGPoint

    // make route animatable head position only
    var animatableData: AnimatablePair<CGFloat, CGFloat> {
        get { AnimatablePair(head.x, head.y) }
        set {
            head.x = newValue.first
            head.y = newValue.second
        }
    }

    func path(in rect: CGRect) -> Path {
        Path { path in
            guard points.count > 1 else { return }
            path.move(to: points.first!)
            _ = points.dropFirst().dropLast().map { path.addLine(to: $0) }
            path.addLine(to: head)
        }
    }
}

// Route view model holding all points and notifying when last one changed
class RouteVM: ObservableObject {
    var points = [CGPoint.zero] {
        didSet {
            self.lastPoint = points.last ?? CGPoint.zero
        }
    }
    @Published var lastPoint = CGPoint.zero
}

struct DemoRouteView: View {
    @ObservedObject var vm = RouteVM()

    var body: some View {
        GeometryReader { gp in
            ZStack { // area
                Rectangle().fill(Color.white)
                    .gesture(DragGesture(minimumDistance: 0).onEnded { value in
                        self.vm.points.append(value.location) // read coordinates in area
                    })

                Circle().fill(Color.blue).frame(width: 20)
                    .position(self.vm.points.first!) // show initial point

                // draw route when head changed, animating
                Route(points: self.vm.points, head: self.vm.lastPoint)
                    .stroke(style: StrokeStyle(lineWidth: 8, lineCap: .round, lineJoin: .miter, miterLimit: 0, dash: [], dashPhase: 0))
                    .foregroundColor(.red)
                    .animation(.linear(duration: 0.5))
            }
            .onAppear {
                let area = gp.frame(in: .global)
                // just initail point at the bottom of screen
                self.vm.points = [CGPoint(x: area.midX, y: area.maxY)]
            }
        }.edgesIgnoringSafeArea(.all)
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SwiftUI - 动画路径形状描边绘图 的相关文章

随机推荐