我正在创建条形图,带有条形动画。我在视图下划线层(这是我的习惯)中绘制它们
BarChartLayer
). 该层负责所有图纸。
我使用名为
procentAnimation
. 在这个值的动态变化过程中,在draw方法中,我计算两个数组的值之间的步长(
oldValues
newValues
).
从oldValues到newValues的第一个动画效果很好。在动画代理中设置动画后,我交换两个数组的值。
第二个动画应该看起来像反转动画。但在动画开始后,条形图跳到第一个动画开始位置,然后像第一个动画一样连续动画,完成后,条形图跳回到第二个动画的最终位置。
在调试模式下,当我添加第二个动画时,我发现属性的值
旧值
新值
保持正确,但当动画在方法中开始时
draw(in:)
价值观
新值
跳回到第一个动画中的场景。
class BarChartLayer: CALayer {
var oldValues: [CGFloat] = [45, 34, 12, 88, 17, 77, 88, 10] {
didSet {
debugPrint("oldValues set")
}
}
var newValues: [CGFloat] = [92, 72, 64, 32, 28, 15, 11, 33] {
didSet {
debugPrint("newValues set")
}
}
var numberOfBars: CGFloat = 8
var space: CGFloat = 10
@objc var procentAnimation : CGFloat = 0
override class func needsDisplay(forKey key: String) -> Bool {
if key == #keyPath(procentAnimation) {
return true
}
return super.needsDisplay(forKey:key)
}
func animateBarsChange() {
let ba = CABasicAnimation(keyPath:#keyPath(BarChartLayer.procentAnimation))
procentAnimation = 100
ba.duration = 4.0
ba.fromValue = 0
ba.delegate = self
add(ba, forKey:nil)
}
func barWidth(rect: CGRect) -> CGFloat {
return (rect.width - CGFloat(space * (numberOfBars - 1))) / CGFloat(numberOfBars)
}
func procentRanndomizer(rect: CGRect) -> CGFloat {
return CGFloat.random(in: 1...100) * rect.height / 100
}
func makeProcentFor(value: CGFloat, rect: CGRect) -> CGFloat {
return value * rect.height / 100
}
func additionalHeight(index: Int) -> CGFloat {
return (newValues[index] - oldValues[index]) / 100
}
func makeRandomArr() -> [CGFloat] {
var arr = [CGFloat]()
for _ in 0..<8 {
arr.append(CGFloat.random(in: 1...100))
}
return arr
}
override func draw(in ctx: CGContext) {
UIGraphicsPushContext(ctx)
let con = ctx
let rect = self.bounds
con.addRect(rect)
con.setFillColor(UIColor.gray.cgColor)
con.fillPath()
var px:CGFloat = 0
let bw = barWidth(rect: rect)
debugPrint("OLD - \(oldValues)")
debugPrint("NEW - \(newValues)")
let oldValues = self.oldValues
for i in 0..<Int(numberOfBars) {
px = CGFloat(i) * (bw + space)
let h = oldValues[i] + procentAnimation * additionalHeight(index: i)
con.addRect(CGRect(x: px, y: 0, width: bw, height: makeProcentFor(value: h, rect: rect)))
}
con.setFillColor(UIColor.green.cgColor)
con.fillPath()
UIGraphicsPopContext()
}
}
extension BarChartLayer: CAAnimationDelegate {
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
if flag {
let temp = self.oldValues
self.oldValues = self.newValues
self.newValues = temp//makeRandomArr()
self.procentAnimation = 0
debugPrint("------------------------------------")
setNeedsDisplay()
}
}
}