问题:当我不更新整个模型时,所有动画均有效。但是,当我在CATransaction.commit之前设置CATextLayer的框架时,CATransaction块中的strokeEnd属性(CAShapelayer.mask)不再具有动画效果。动画从笔画结束开始。最终值几乎没有出现。但是,当我跳过这一行来设置框架时,一切正常,但是模型部分不同步。
我要实现的目标:所有动画的运行和建模均与动画的结束状态保持同步
非工作解决方案:
您有什么可以解决的解决方法?
class CircleChartLayer: CALayer {
/// Animated progressArc with gradient filling that shows current value
private let progressArcLayer = CAGradientLayer()
/// Animated knobCircle that shows current value
private let knobCircleLayer = CAShapeLayer()
// Animated label that shows current value
private let labelLayer = CATextLayer()
override init(layer: Any) {
super.init(layer: layer)
setupGradient()
setupLabel()
self.addSublayer(progressArcLayer)
self.addSublayer(knobCircleLayer)
self.addSublayer(labelLayer)
}
override func layoutSublayers() {
setFrames()
}
func animate(to value: Double, withDuration duration: TimeInterval, completion: ((Bool) -> Void)?) {
// if ring.isAnimating {
// ring.pauseAnimation()
// }
/// Current mask of the progressArcLayer
let maskLayer = progressArcLayer.mask as! CAShapeLayer
/// Animation 1 for filling (gradient) of progressArcLayer
let gradientAnimation = animateGradientLayer()
/// Animation 2 for mask/position of progressArcLayer
let shapeAnimation = animateShapeProgressArc()
/// Animation 3 knobCircle at end of progressArcLayer
let knobPositionAnimation = animateKnobPosition()
/// Animation 4 for positioning of layer
let labelPositionAnimation = animateLabelPosition()
/// Sync all animations
CATransaction.begin()
CATransaction.setDisableActions(true)
CATransaction.setAnimationDuration(duration) //duration for both animations
CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: .easeInEaseOut))
// Add animations and snyc model
progressArcLayer.add(gradientAnimation, forKey: #keyPath(CAGradientLayer.endPoint))
progressArcLayer.endPoint = stepsEndpoints.last!
progressArcLayer.mask?.add(shapeAnimation, forKey: "strokeEnd")
maskLayer.strokeEnd = CGFloat(value / progressArc.maxValue)
knobCircleLayer.add(knobPositionAnimation, forKey: #keyPath(CAShapeLayer.transform))
progressArc.value = value
updateKnob()
labelLayer.add(labelPositionAnimation, forKey: "path")
/// THE NEXT LINE BREAKS THE "STROKEND" ANIMATION
// When I remove the line all the animations work fine but the sync
// of the labelLayer is missing at the end of the animation
labelLayer.frame = knobCircleLayer.bounds
CATransaction.commit()
}
/// Animates the background of the progressArcLayer
func animateGradientLayer() -> CAKeyframeAnimation {
let animateGradient = CAKeyframeAnimation(keyPath: #keyPath(CAGradientLayer.endPoint))
animateGradient.values = endPoints
animateGradient.beginTime = 0
return animateGradient
}
/// Animates the shape of the progressArcLayer
func animateShapeProgressArc() -> CAKeyframeAnimation {
let animateShape = CAKeyframeAnimation(keyPath: #keyPath(CAShapeLayer.strokeEnd))
animateShape.values = values
animateShape.beginTime = 0
return animateShape
}
/// Animates the knop position which shows the current value
func animateKnobPosition() -> CAKeyframeAnimation {
let animateKnob = CAKeyframeAnimation(keyPath: #keyPath(CAShapeLayer.transform))
animateKnob.values = transformationValues
animateKnob.beginTime = 0
return animateKnob
}
func animateLabelPosition(to radSteps: [CGFloat]) -> CAKeyframeAnimation {
let animateLabel = CAKeyframeAnimation(keyPath: "position")
animateLabel.path = path
animateLabel.beginTime = 0
return animateLabel
}
}