如何强制更新以呈现连续路径

问题描述

我目前正在制作路径上的连续动画。路径应定期使用新值更新,更新应使用这些值触发新动画的开始。我在尝试使用新值刷新视图时遇到问题。带路径的动画在动画开始时显示,在尝试从方法触发视图更新后,它没有显示任何新视图或更新的路径。就是白屏。我用于此视图和更新的代码是:

包装在 UIViewRepresentable 中的图表视图:

struct AnimatedChartView: UIViewRepresentable {

let geometryProxy: GeometryProxy
let leadValues: [Float]//Binding<[Float]>
//Chart control values
//step coefficinet
let xStepCoefficient: CGFloat = 0.00035
//Single step on view
var xStep: CGFloat{
    let xStepValue = xStepCoefficient * geometryProxy.frame(in: .local).width
    return xStepValue
}

var rootView: UIView
var chartLayer: CAShapeLayer
//Make chart view with animation
func makeUIView(context: Context) -> some UIView {
    //Prepare view for animation and chart
    
    chartLayer.delegate = context.coordinator
    rootView.layer.addSublayer(chartLayer)
    
    return rootView
}
init(geometry: GeometryProxy,values: [Float]) {
    
    rootView = UIView()
    geometryProxy = geometry
    leadValues = values
    chartLayer = CAShapeLayer()
    chartLayer = prepareAnimationLayer()
}
//Update viewu
func updateUIView(_ uiView: UIViewType,context: Context) {
    print("Update uiView")
    
    dispatchQueue.main.async {
        let newChartLayer = prepareAnimationLayer()
        rootView.layer.addSublayer(newChartLayer)
        rootView.setNeedsdisplay()
    }
}

//Assign
func makeCoordinator() -> Coordinator {
    Coordinator(self)
}

//Delegates from view
class Coordinator: NSObject,CALayerDelegate {
    var parent: AnimatedChartView
    
    init(_ parentView: AnimatedChartView) {
        self.parent = parentView
    }
    
    func draw(_ layer: CALayer,in ctx: CGContext) {
        print("Drawing layer in context")
        
    }
    func layerWillDraw(_ layer: CALayer) {
        print("layer will draw")
    }
}
//Assign animation layer for chart
private func prepareAnimationLayer() -> CAShapeLayer {
    //Create animation proeprties
    let chartLayer = CAShapeLayer()
    let strokeAnimation = makeAnimation()
    let chartPath = makeChartFromValues(newValues: leadValues)
    //Assign path and marks start and end of stroke to animate
    chartLayer.path = chartPath.cgPath
    chartLayer.strokeStart = 0.0
    chartLayer.strokeEnd = 0.0
    chartLayer.strokeColor = UIColor.green.cgColor
    chartLayer.linewidth = 2
    chartLayer.fillColor = UIColor.clear.cgColor
    chartLayer.add(strokeAnimation,forKey: "strokeAnimation")
    
    return chartLayer
}

//Setup chart animation
private func makeAnimation() -> CABasicAnimation{
    let strokeEndAnimation = CABasicAnimation(keyPath: "strokeEnd")
    //Prepare animation
    strokeEndAnimation.fromValue = 0.0
    strokeEndAnimation.tovalue = 1.0
    strokeEndAnimation.duration = 1
    strokeEndAnimation.timingFunction = camediatimingFunction(name: .easeInEaSEOut)
    strokeEndAnimation.repeatCount = 0
    strokeEndAnimation.duration = 1
    
    return strokeEndAnimation
}

//makes chart path
private func makeChartFromValues(newValues: [Float]) -> UIBezierPath{
    let chartPath = UIBezierPath(roundedRect: CGRect(origin: .zero,size: .init(width: 200,height: 120)),byRoundingCorners: .allCorners,cornerRadii: .zero)
    
    chartPath.move(to: .zero)
    
    var currentX = xStep
    
    newValues.forEach{ value in
        //Value point to draw
        let nextPoint = CGPoint(x: currentX,y: CGFloat(value / 1000))
        //Adds line to chart
        chartPath.addLine(to:nextPoint)
        //Move to next value
        currentX += xStep
    }
    return chartPath
    
}

}

和带有更新值的定时器的视图模型的视图函数

struct UIKitAnimatedpathView: View {
@State var animationRect: CGRect = CGRect(origin: .zero,size: CGSize(width: 200,height: 200))
@StateObject var viewmodel = Animationviewmodel()

var body: some View {
    GeometryReader{ geo in
        vstack(content: {
            ForEach(0 ..< 18,id: \.self){ i in
                AnimatedChartView(geometry: geo,values: viewmodel.values)
            }
        })
    }
}

}

视图模型:

class Animationviewmodel: ObservableObject{

@Published var values: [Float] = [Float](repeating: 1,count: 2000)

@Published var timer: Timer?

init() {
    timer = Timer.scheduledTimer(withTimeInterval: 1,repeats: true,block: {time in
    //print("time in: \(time.timeInterval)")
        
        var vals:[Float] = []
            for _ in 0 ..< 2000{
            let rand = Float.random(in: -20000 ..< 0)
            vals.append(rand)
        }
        self.values.removeAll()
        self.values = vals
    
    })
}

}

你可以看到注释掉了部分代码,因为我试图让它以某种方式工作,但到目前为止没有运气......我想要实现的功能是不断更新图表。此代码适用于首次运行。预先感谢您提供有关如何使其工作的任何指导:))

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...