在 Swift 中动画化 CAShapeLayer 路径从旧值到新值
Animate CAShapeLayer path from old value to new value in Swift
我是 Core Animation 的新手,我正在尝试根据新数据将 CAShapeLayer
的 strokeEnd
从旧值更新为新的更新值。
所以基本上我有一个绘制的 CAShapeLayer
,并更新它 UIBezierPath
,并使用 CABasicAnimation(forKey: "strokeEnd")
来为新的 strokeEnd
设置动画:
layerAnimation = CABasicAnimation(keyPath: "strokeEnd")
layerAnimation.toValue = 1
shapeLayer.strokeEnd = 1
layerAnimation.duration = 0.4
shapeLayer.add(layerAnimation, forKey: animation.identifier)
其中 animation.identifier
是一个 String Enum
值,它确定应使用哪个动画。
到目前为止,我一直在深入研究 Apple 的 Core Animation 文档,并在此处的堆栈溢出中寻找可能的线索,但到目前为止还没有任何运气。
据我所知,通过在动画中只分配一个值,核心动画会自己找出路径,但到目前为止还没有成功。我还尝试计算新旧最高 Y 值之间的差异,并使用 byValue
,有无 fromValue
或 toValue
。
绘制了更新的路径,但遗憾的是 strokeEnd
更新后没有显示动画。
任何帮助、提示或建议,我们将不胜感激。
干杯!
编辑以根据@matt 的反馈添加更多详细信息:TLDR;更新路径,我想我应该用 toValue 制作动画。
我正在存储一个数组,其中包含 CAShapeLayer
之后的 UIBezierPath
。路径是根据可以是三个不同值的数据确定的,应该从 (x: i, y: 0) -> (x: i, y: n) 开始。其中 x 是一个固定位置,y 是路径的终点,在给定的 array[i] 列中。
如果第i个位置的数据有更新,我重新计算UIBezierPath
,这是在newPath(x:y:h:) -> UIBezierPath
中完成的
if let previous: CAShapeLayer = previousColumns[i] {
shapeLayer = previous
bezierPath = UIBezierPath()
bezierPath = newPath(x: xPoint(i), y: newY, viewHeight: height)
shapeLayer.path = bezierPath.cgPath
animate(shapeLayer: shapeLayer, animation: .updateAnimation)
} else { draw new CAShapeLayer with UIBezierPath }
animate(shapeLayer:animation:)
包含首先提到的代码,据我了解,在动画发生之前,应该将 CABasicAnimation
或 CAKeyFrameAnimation
添加到给定的 CAShapeLayer
.
好的,经过一些指导,@matt 让我意识到,应该更新的不是 strokeEnd,而是路径。因此,通过稍微调整我的代码,我意识到通过将要绘制的新列的 UIBezierPath
首先设置为旧列,然后创建新路径,我可以使用 [= 为路径设置动画13=] 对于路径,使用来自值的动画作为旧路径,并将 toValue 作为新值。
if let previous: CAShapeLayer = previousColumns[i], let oldPath: CGPath = previous.path {
shapeLayer = previous
bezierPath = UIBezierPath(cgPath: oldPath)
shapeLayer.path = bezierPath.cgPath
let newBezierPath = newPath(x: x, y: newY, viewHeight: height)
animate(shapeLayer: shapeLayer, animation: .updateAnimation, newBezierPath: newBezierPath.cgPath)
}
然后更新动画块:
layerAnimation = CABasicAnimation(keyPath: "path")
layerAnimation.fromValue = shapeLayer.path
layerAnimation.toValue = newBezierPath
shapeLayer.path = newBezierPath
再一次,如果没有@matt 的有用提示,我无法解决这个问题,所以谢谢@matt! :)
我是 Core Animation 的新手,我正在尝试根据新数据将 CAShapeLayer
的 strokeEnd
从旧值更新为新的更新值。
所以基本上我有一个绘制的 CAShapeLayer
,并更新它 UIBezierPath
,并使用 CABasicAnimation(forKey: "strokeEnd")
来为新的 strokeEnd
设置动画:
layerAnimation = CABasicAnimation(keyPath: "strokeEnd")
layerAnimation.toValue = 1
shapeLayer.strokeEnd = 1
layerAnimation.duration = 0.4
shapeLayer.add(layerAnimation, forKey: animation.identifier)
其中 animation.identifier
是一个 String Enum
值,它确定应使用哪个动画。
到目前为止,我一直在深入研究 Apple 的 Core Animation 文档,并在此处的堆栈溢出中寻找可能的线索,但到目前为止还没有任何运气。
据我所知,通过在动画中只分配一个值,核心动画会自己找出路径,但到目前为止还没有成功。我还尝试计算新旧最高 Y 值之间的差异,并使用 byValue
,有无 fromValue
或 toValue
。
绘制了更新的路径,但遗憾的是 strokeEnd
更新后没有显示动画。
任何帮助、提示或建议,我们将不胜感激。
干杯!
编辑以根据@matt 的反馈添加更多详细信息:TLDR;更新路径,我想我应该用 toValue 制作动画。
我正在存储一个数组,其中包含 CAShapeLayer
之后的 UIBezierPath
。路径是根据可以是三个不同值的数据确定的,应该从 (x: i, y: 0) -> (x: i, y: n) 开始。其中 x 是一个固定位置,y 是路径的终点,在给定的 array[i] 列中。
如果第i个位置的数据有更新,我重新计算UIBezierPath
,这是在newPath(x:y:h:) -> UIBezierPath
if let previous: CAShapeLayer = previousColumns[i] {
shapeLayer = previous
bezierPath = UIBezierPath()
bezierPath = newPath(x: xPoint(i), y: newY, viewHeight: height)
shapeLayer.path = bezierPath.cgPath
animate(shapeLayer: shapeLayer, animation: .updateAnimation)
} else { draw new CAShapeLayer with UIBezierPath }
animate(shapeLayer:animation:)
包含首先提到的代码,据我了解,在动画发生之前,应该将 CABasicAnimation
或 CAKeyFrameAnimation
添加到给定的 CAShapeLayer
.
好的,经过一些指导,@matt 让我意识到,应该更新的不是 strokeEnd,而是路径。因此,通过稍微调整我的代码,我意识到通过将要绘制的新列的 UIBezierPath
首先设置为旧列,然后创建新路径,我可以使用 [= 为路径设置动画13=] 对于路径,使用来自值的动画作为旧路径,并将 toValue 作为新值。
if let previous: CAShapeLayer = previousColumns[i], let oldPath: CGPath = previous.path {
shapeLayer = previous
bezierPath = UIBezierPath(cgPath: oldPath)
shapeLayer.path = bezierPath.cgPath
let newBezierPath = newPath(x: x, y: newY, viewHeight: height)
animate(shapeLayer: shapeLayer, animation: .updateAnimation, newBezierPath: newBezierPath.cgPath)
}
然后更新动画块:
layerAnimation = CABasicAnimation(keyPath: "path")
layerAnimation.fromValue = shapeLayer.path
layerAnimation.toValue = newBezierPath
shapeLayer.path = newBezierPath
再一次,如果没有@matt 的有用提示,我无法解决这个问题,所以谢谢@matt! :)