Search code examples
swiftcore-animation

"path" animation with CABasicAnimation - Turn "x" into a checkmark


I want to animate a 'morph' from "x" to a checkmark: So this:

The start path

should turn into this (animated):

enter image description here

I created those paths separately (see code below) but when I try to animate them with CABasicAnimation I get this instead of the cross at the beginning:

enter image description here

And this then turns into the checkmark. Why? And how can I fix it? Or doesn't this work with CABasicAnimation?

// just the blue background
    let shapeLayer = CAShapeLayer()
    shapeLayer.frame = CGRect(x: 0, y: 0, width: bounds.height, height: bounds.height)
    shapeLayer.backgroundColor = UIColor.blue.cgColor
    layer.addSublayer(shapeLayer)


    // first path (the "x")
    let padding: CGFloat = 10
    let crossPath = UIBezierPath()
    crossPath.move(to: CGPoint(x: padding, y: padding))
    crossPath.addLine(to: CGPoint(x: bounds.height - padding, y: bounds.height - padding))
    crossPath.move(to: CGPoint(x: bounds.height - padding, y: padding))
    crossPath.addLine(to: CGPoint(x: padding, y: bounds.height - padding))

    // Create the shape layer that will draw the path
    let signLayer = CAShapeLayer()
    signLayer.frame = bounds
    signLayer.path = crossPath.cgPath // setting the path from above
    signLayer.strokeColor = UIColor.white.cgColor
    signLayer.fillColor = UIColor.clear.cgColor
    signLayer.lineWidth = 4

    // add it to your view's layer and you're done!
    layer.addSublayer(signLayer)

    let anim: CABasicAnimation = CABasicAnimation(keyPath: "path")
    anim.duration = 10.0 // just a test value to see the animation more clearly

    // the checkmark
    let checkmarkPath = UIBezierPath()
    checkmarkPath.move(to: CGPoint(x: bounds.height - padding, y: padding))
    checkmarkPath.addLine(to: CGPoint(x: 2 * padding, y: bounds.height -  padding))
    checkmarkPath.addLine(to: CGPoint(x: padding, y: bounds.height / 2))

    anim.fromValue = crossPath.cgPath
    anim.toValue = checkmarkPath.cgPath

    signLayer.path = checkmarkPath.cgPath
    signLayer.add(anim, forKey: "path")

Solution

  • To animate correctly, you need to animate between 2 paths with the same number of points. Your crossPath has 4 points and checkmarkPath has 3.