Apple's documentation link states that:
The fromValue, byValue and toValue properties define the values being interpolated between. All are optional, and no more than two should be non-nil. The object type should match the type of the property being animated.
The interpolation values are used as follows:
- All properties are nil. Interpolates between the previous value of keyPath in the target layer’s presentation layer and the current value of keyPath in the target layer’s presentation layer.
How can I make this work without specifying any of the fromValue
, byValue
, or toValue
?
Here, I'm just animating the change of the cornerRadius
property.
I know how to make this animation using toValue
. But I just want to know if there is an even simpler code than this to achieve it:
import UIKit
import PlaygroundSupport
let rect = CGRect(x: 0,y: 0, width: 300, height: 400)
let view = UIView(frame: rect)
view.backgroundColor = UIColor.yellow
PlaygroundPage.current.liveView = view
let layer = CALayer()
layer.backgroundColor = UIColor.red.cgColor
layer.frame = CGRect(x: 75, y: 75, width: 150, height: 150)
view.layer.addSublayer(layer)
layer.cornerRadius = 15
let animation = CABasicAnimation(keyPath:#keyPath(CALayer.cornerRadius))
animation.toValue = layer.bounds.width / 2
animation.duration = 1
layer.add(animation, forKey: nil)
In some situations, where you have already set the layer's final value without animation, you can skip setting both the toValue
and the fromValue
in your CABasicAnimation, because the runtime gets the fromValue
from the current value of the presentation layer and the toValue
from the current value of the model layer.
For example, in my own code, it turns out that I can reduce this full form of specifying an animation...
let startValue = arrow.transform
let endValue = CATransform3DRotate(startValue, .pi/4.0, 0, 0, 1)
CATransaction.setDisableActions(true)
arrow.transform = endValue
let anim = CABasicAnimation(keyPath:#keyPath(CALayer.transform))
anim.duration = 0.8
let clunk = CAMediaTimingFunction(controlPoints:0.9, 0.1, 0.7, 0.9)
anim.timingFunction = clunk
anim.fromValue = startValue
anim.toValue = endValue
arrow.add(anim, forKey:nil)
...to this (notice that fromValue
and toValue
are omitted):
CATransaction.setDisableActions(true)
arrow.transform = CATransform3DRotate(arrow.transform, .pi/4.0, 0, 0, 1)
let anim = CABasicAnimation(keyPath:#keyPath(CALayer.transform))
anim.duration = 0.8
let clunk = CAMediaTimingFunction(controlPoints:0.9, 0.1, 0.7, 0.9)
anim.timingFunction = clunk
arrow.add(anim, forKey:nil)
However, I do not recommend that approach. It is much more reliable always to supply both the fromValue
and the toValue
. Yes, it's two more lines of code, but that is a small price to pay for avoiding confusion. Sometimes, clarity is simplicity.