gpt4 book ai didi

ios - CALayer (CAAnimation) 可动画属性绘制错误

转载 作者:行者123 更新时间:2023-11-29 05:15:56 26 4
gpt4 key购买 nike

我正在创建带条形动画的条形图。我将它们绘制在 View 下划线层中(这是我的自定义 BarChartLayer )。该层负责所有绘图。

对于动画图表栏,我使用名为 procentAnimation 的可动画属性.在该值的动画变化期间,在绘制方法中,我计算两个数组的值之间的步长( oldValuesnewValues )。

从 oldValues 到 newValues 的第一个动画效果很好。在动画委​​托中执行动画之后,我交换两个数组的值。

第二个动画应该看起来像反向动画。但是在动画开始后,条形图跳到第一个动画开始位置,然后动画像第一个动画一样连续,完成后图表条形图跳回到第二个动画的最终位置。

在 Debug模式下,我发现,当我添加第二个动画时,属性值 oldValuesnewValues保持正确,但是当动画在方法 draw(in:) 中开始时oldValues 的值和 newValues跳回第一个动画期间的情况。

这是一个错误还是有一些我不明白的机制?如何解决这个问题?

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()
}
}
}

最佳答案

您应该使用 @NSManaged 标记自定义可动画属性,因为 Core Animation 会创建模型层的副本以进行渲染。 @NSManaged 不允许使用默认值。所以你应该重写 defaultValue(forKey:)

@NSManaged var procentAnimation : CGFloat

override class func defaultValue(forKey inKey: String) -> Any? {
return inKey == "procentAnimation" ? 0.0 : super.defaultValue(forKey: inKey)
}

您也不应该在 CALayer 实现中使用 UIKit 函数。因此,您应该将 UIGraphicsPushContextUIGraphicsPopContext 替换为 Core Graphics 对应项:

override func draw(in ctx: CGContext) {
ctx.saveGState()
...
ctx.restoreGState()
}

关于ios - CALayer (CAAnimation) 可动画属性绘制错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59185344/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com