Connect two strokeEnd animations

I am trying to make a user activity indicator similar to an activity indicator showing the circular uncertainty of Android activity. Basically, I want to draw a circle twice and erase it, but erasing and drawing does not happen at the same time or quickly. This is what I still have:

let progressLayer = CAShapeLayer() progressLayer.strokeColor = UIColor.red().cgColor progressLayer.fillColor = nil progressLayer.lineWidth = 2 let drawAnimation = CABasicAnimation(keyPath: "strokeEnd") drawAnimation.duration = duration / 2 drawAnimation.fromValue = 0 drawAnimation.toValue = 1 drawAnimation.isRemovedOnCompletion = false drawAnimation.fillMode = kCAFillModeForwards let eraseAnimation = CABasicAnimation(keyPath: "strokeStart") eraseAnimation.duration = duration / 2 eraseAnimation.beginTime = 0.2 eraseAnimation.fromValue = 0 eraseAnimation.toValue = 0.4 eraseAnimation.isRemovedOnCompletion = false eraseAnimation.fillMode = kCAFillModeForwards let endDrawAnimation = CABasicAnimation(keyPath: "strokeEnd") endDrawAnimation.beginTime = duration / 2 endDrawAnimation.duration = duration / 2 endDrawAnimation.fromValue = 0 endDrawAnimation.toValue = 1 endDrawAnimation.isRemovedOnCompletion = false endDrawAnimation.fillMode = kCAFillModeForwards let endEraseAnimation = CABasicAnimation(keyPath: "strokeStart") endEraseAnimation.beginTime = duration / 2 endEraseAnimation.duration = duration / 4 endEraseAnimation.fromValue = 0.4 endEraseAnimation.toValue = 1 endEraseAnimation.isRemovedOnCompletion = false endEraseAnimation.fillMode = kCAFillModeForwards let endEraseAnimation2 = CABasicAnimation(keyPath: "strokeStart") endEraseAnimation2.beginTime = duration * 3 / 4 endEraseAnimation2.duration = duration / 4 endEraseAnimation2.fromValue = 0 endEraseAnimation2.toValue = 1 endEraseAnimation2.isRemovedOnCompletion = false endEraseAnimation2.fillMode = kCAFillModeForwards let animations = CAAnimationGroup() animations.duration = duration animations.animations = [drawAnimation, eraseAnimation, endDrawAnimation, endEraseAnimation, endEraseAnimation2] animations.isRemovedOnCompletion = false animations.fillMode = kCAFillModeForwards progressLayer.add(animations, forKey: "stroke") 

The code does everything as expected, except for one problem. When the first strokeEnd animation strokeEnd complete and the second begins, there is some kind of flash meaning the part of the circle that was drawn until this point disappears, and then the pattern starts again from 0. Does anyone have any ideas how to fix it

+8
ios animation swift swift3 core-animation
source share
1 answer

When the first strokeEnd animation is executed, and the second one starts, there is a kind of flash, meaning the part of the circle that was drawn until this point disappears, and then drawing starts from 0.

If you compare the settings of both drawAnimation and endDrawAnimation , you will see that they are identical, except for the beginTime . That is why you flicker. They both start at 0 and both end at 1. Since you did not specify the desired result, I can simply assume that you want endDrawAnimation have fromValue of 1.

 let drawAnimation = CABasicAnimation(keyPath: "strokeEnd") drawAnimation.duration = duration / 2 drawAnimation.fromValue = 0 drawAnimation.toValue = 1 drawAnimation.isRemovedOnCompletion = false drawAnimation.fillMode = kCAFillModeForwards let endDrawAnimation = CABasicAnimation(keyPath: "strokeEnd") endDrawAnimation.beginTime = duration / 2 // Starts after the first animation and starts with 0 again. endDrawAnimation.duration = duration / 2 endDrawAnimation.fromValue = 0 endDrawAnimation.toValue = 1 endDrawAnimation.isRemovedOnCompletion = false endDrawAnimation.fillMode = kCAFillModeForwards 

Suggestion for improvement

As far as I see, you want to create a keyframe animation, which means that you have predefined offsets at which the animation behavior changes (speed, value, etc.). You might want to use CAKeyframeAnimation .

I'm not sure what you know about this, but at the moment you have two animations running simultaneously on strokeStart :

  • eraseAnimation starting with 0.2 with a duration of 0.5 * duration
  • endEraseAnimation starting with 0.5 * duration .

This means that the end of eraseAnimation ( 0.2 + 0.5 * duration ) is always greater than the beginning of endEraseAnimation ( 0.5 * duration )

0
source share

All Articles