In my app i am using a third party library which does circular animation just like in the appstore app download animation. i am using the external file which i have placed in my project. it works but when the timer reaches to 5 seconds the fill color should be red. Currently the whole layer red color applies, i want to only apply the portion it has progressed. i am attaching the video and the third party file. Please can anyone help me with this as what changes should i make to the library file or is there better solution
same video link in case google drive link doesnt work
External Library link which i am using
My code snippet that i have tried:
func startGamePlayTimer(color: UIColor)
{
if !isCardLiftedUp {
self.circleTimerView.isHidden = false
self.circleTimerView.timerFillColor = color
Constants.totalGamePlayTime = 30
self.circleTimerView.startTimer(duration: CFTimeInterval(Constants.totalGamePlayTime))
}
if self.gamePlayTimer == nil
{
self.gamePlayTimer?.invalidate()
let timer = Timer.scheduledTimer(timeInterval: 1.0,
target: self,
selector: #selector(updateGamePlayTime),
userInfo: nil,
repeats: true)
timer.tolerance = 0.05
RunLoop.current.add(timer, forMode: .common)
self.gamePlayTimer = timer
}
}
@objc func updateGamePlayTime()
{
if Constants.totalGamePlayTime > 0
{
Constants.totalGamePlayTime -= 1
if Constants.totalGamePlayTime < 5
{
SoundService.playSound(sound: .turn_timeout)
self.circleTimerView.timerFillColor = UIColor.red.withAlphaComponent(0.7)
}
}
else
{
self.stopGamePlayTimer()
}
}
where circleTimerView is the view which animates as the time progresses
You can achieve that with CAKeyframeAnimation
on the StrokePath
.
I've Update the code in CircleTimer
View as below. You can modified fill color and time as per your need.
@objc func updateGamePlayTime()
{
if Constants.totalGamePlayTime > 0
{
Constants.totalGamePlayTime -= 1
if Constants.totalGamePlayTime < 5
{
SoundService.playSound(sound: .turn_timeout)
// self.circleTimerView.timerFillColor = UIColor.red.withAlphaComponent(0.7) // <- Comment this line
}
}
else
{
self.stopGamePlayTimer()
}
}
open func drawFilled(duration: CFTimeInterval = 5.0) {
clear()
if filledLayer == nil {
let parentLayer = self.layer
let circleLayer = CAShapeLayer()
circleLayer.bounds = parentLayer.bounds
circleLayer.position = CGPoint(x: parentLayer.bounds.midX, y: parentLayer.bounds.midY)
let circleRadius = timerFillDiameter * 0.5
let circleBounds = CGRect(x: parentLayer.bounds.midX - circleRadius, y: parentLayer.bounds.midY - circleRadius, width: timerFillDiameter, height: timerFillDiameter)
circleLayer.fillColor = timerFillColor.cgColor
circleLayer.path = UIBezierPath(ovalIn: circleBounds).cgPath
// CAKeyframeAnimation: Changing Fill Color on when timer reaches 80% of total time
let strokeAnimation = CAKeyframeAnimation(keyPath: "fillColor")
strokeAnimation.keyTimes = [0, 0.25, 0.75, 0.80]
strokeAnimation.values = [timerFillColor.cgColor, timerFillColor.cgColor, timerFillColor.cgColor, UIColor.red.withAlphaComponent(0.7).cgColor]
strokeAnimation.duration = duration;
circleLayer.add(strokeAnimation, forKey: "fillColor")
parentLayer.addSublayer(circleLayer)
filledLayer = circleLayer
}
}
open func startTimer(duration: CFTimeInterval) {
drawFilled(duration: duration) // <- Need to pass duration here
if useMask {
runMaskAnimation(duration: duration)
} else {
runDrawAnimation(duration: duration)
}
}
UPDATE:
CAKeyframeAnimation:
values
and keyTimes
properties.For example:
let colorKeyframeAnimation = CAKeyframeAnimation(keyPath: "backgroundColor")
colorKeyframeAnimation.values = [UIColor.red.cgColor,
UIColor.green.cgColor,
UIColor.blue.cgColor]
colorKeyframeAnimation.keyTimes = [0, 0.5, 1]
colorKeyframeAnimation.duration = 2
This animation will run for the 2.0
duration.
i.e:
KeyTime 0.5
-> (2 * 0.5) -> At 1 sec
during animation -> UIColor.green.cgColor
will be shown.
Now to answer your question from the comments, Suppose we have timer of 25 seconds and we want to show some value for last 10 seconds, we can do:
strokeAnimation.keyTimes = [0, 0.25, 0.50, 0.60]
strokeAnimation.values = [timerFillColor.cgColor,timerFillColor.cgColor, timerFillColor.cgColor, timerFillColor.cgColor, UIColor.red.withAlphaComponent(0.7).cgColor]
strokeAnimation.duration = 25.0 // Let's assume duration is 25.0