Search code examples
iosswiftanimationcore-graphicscore-animation

iOS Swift how to synchronise chart drawing line, gradient and circle animations?


I try to synchronise animations of chart line, circle and gradient.

Here is fancy chart gif with not synchronised animations :/ chart animation

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)
  1. Gradient animation is not synchronised because distance over path is different from straight line, anyone has idea how to synchronise this?

  2. 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?


Solution

  • 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.