问题描述
我目前正在制作路径上的连续动画。路径应定期使用新值更新,更新应使用这些值触发新动画的开始。我在尝试使用新值刷新视图时遇到问题。带路径的动画在动画开始时显示,在尝试从方法触发视图更新后,它没有显示任何新视图或更新的路径。就是白屏。我用于此视图和更新的代码是:
包装在 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 (将#修改为@)