I try to synchronise animations of chart line, circle and gradient.
Here is fancy chart gif with not synchronised animations :/
Run all animations code:
CATransaction.begin()
CATransaction.setAnimationDuration(5.0)
CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut))
self?.animateLineDrawing()
self?.animateGradient()
self?.animateCircle()
CATransaction.commit()
Line drawing animation:
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.fromValue = 0.0
animation.toValue = 1.0
lineShapeLayer.add(animation, forKey: "drawLineAnimation")
lineShapeLayer.path = curvedPath.cgPath
I have gradientContainer layer with gradientLayer as sublayer. I move only container mask layer over gradient Layer:
let animationPath = UIBezierPath(rect: CGRect(x: firstPoint.x,
y: chartRect.origin.y,
width: 0,
height: chartRect.height))
let animation = CABasicAnimation(keyPath: "path")
animation.fromValue = animationPath.cgPath
animation.toValue = UIBezierPath(rect: CGRect(x: firstPoint.x,
y: chartRect.origin.y,
width: chartRect.width,
height: chartRect.height)).cgPath
animation.isRemovedOnCompletion = false
animation.fillMode = CAMediaTimingFillMode.forwards
animation.delegate = self
gradientContainerLayer.mask?.add(animation, forKey: nil)
Circle animation over chart path:
let animation = CAKeyframeAnimation(keyPath: "position")
animation.path = viewModel.curvedPath(frame)?.cgPath
animation.delegate = self
circleLayer.add(animation, forKey: nil)
Gradient animation is not synchronised because distance over path is different from straight line, anyone has idea how to synchronise this?
Why circle animation timing is not equal to line animation? It look like begin and end of animations are equal so timing functions are different, why?
Instead of using basic and property animation switch all on CAKeyframeAnimation
. I personally found them way simpler to tweak and more flexible in general.
Calculate position for every element to be in same x
coordinate at same time point.
You should consider adding minimum 1 point in each point of interest (change between decreasing and increasing of y
coordinate) so you do not cut local extremes.