How to remove original path when animating path on CAShapeLayer

I'm creating a crude animation of a changing smile using Core Animation. I'm using CAShapeLayer, CAKeyframeAnimation, and UIBezierPath objects to create the paths that change/animate. The problem I'm seeing is that the original path drawn (i.e. the first keyframe in the set of keyframe values) remains throughout the animation. I was expecting it to only be there for the start of the animation and then animate to the next keyframe value...however, it remains and I would like to get rid of it.

Here are some code snippets of my work so far:



        let width: CGFloat = 240
        let height: CGFloat = 120
    
        let shapeLayer = CAShapeLayer()
        shapeLayer.frame = CGRect(x: 0, y: 0,
                                  width: width, height: height)
        shapeLayer.strokeColor = UIColor.red.cgColor
        shapeLayer.lineWidth = 2
        shapeLayer.fillColor = UIColor.clear.cgColor
    
        view1.layer.addSublayer(shapeLayer)



        let keyframeAnimation = CAKeyframeAnimation(keyPath: "path")
        keyframeAnimation.values =
            [

                smile(state: .expressionless).cgPath,
                smile(state: .grin).cgPath,
                smile(state: .expressionless).cgPath,
                smile(state: .frown).cgPath,
                smile(state: .expressionless).cgPath
            ]
        keyframeAnimation.duration = 5
        keyframeAnimation.calculationMode = .cubic
        // keeps the animation in its final state and doesn't revert to its original shape
        keyframeAnimation.isRemovedOnCompletion = false
        keyframeAnimation.fillMode = CAMediaTimingFillMode.forwards


        shapeLayer.add(keyframeAnimation, forKey: nil)


and the smile code function and related enum:





enum SmileState {
        case grin
        case frown
        case expressionless
        case veryhappy
    }
   
    func smile(state: SmileState) -> UIBezierPath {
        let curve = UIBezierPath()
        if (state == .frown) {
            curve.move(to: CGPoint(x: 0, y: 110))
            curve.addQuadCurve(to: CGPoint(x: 240, y: 110), controlPoint: CGPoint(x: 120, y: -290))
        }
        else if (state == .expressionless) {
            curve.move(to: CGPoint(x: 0, y: 60))
            curve.addQuadCurve(to: CGPoint(x: 240, y: 60), controlPoint: CGPoint(x: 120, y: 60))
        }
        else if (state == .grin) {
            curve.move(to: CGPoint(x: 0, y: 10))
            curve.addQuadCurve(to: CGPoint(x: 240, y: 10), controlPoint: CGPoint(x: 120, y: 350))
        }

        curve.close()
        return curve
    }





Any suggestions on what I could do to remove that "expressionless" path as soon as the animation starts?

Accepted Reply

With fresh eyes, I realized that I was "closing" the path, which was my problem. A silly mistake...

Replies

With fresh eyes, I realized that I was "closing" the path, which was my problem. A silly mistake...

lol, the same thing happened with me when I was developing an app related to electric smokers 😀 Thank God it is fixed now.

ha ha ha.... i tried to fix the error while i was working on best sewing machine app. But i have no idea how i was able to solve the issue.