iOS UIKit Animation Library that uses the Metal for the heavy lifting.
It provides an elegant swift API for animating any attributes you like.
Save CPU time for handing events instead of calculation animation steps.
NOTE: This is currently in BETA, use at caution.
- Installation
- Usage
- Animation Attributes
- Parallel Execution
- Serial Execution
- Advance Controls
- UIView Animatable Properties
- Animating Custom Properties
Cocoapods
use_frameworks!
pod "GPUAnimation"
view.animate {
$0.alpha.target = 0.5
$0.center.target = CGPoint(x:100,y:200)
}.delay(2.0).animate {
$0.center.target = CGPoint(x:50,y:50)
$0.center.onChange = { newAlpha in
print(newAlpha)
}
$0.backgroundColor.target = UIColor.black
}.then {
print("Animation completed")
}
GPUAnimation runs all animations like a spring. There is no way to specify the duration of the animation.
This is to ensure that your object follows a physics like smooth velocity curve.
Even if you change the animation target, the object maintains its velocity and follow a natural curve to its new target.
You can adjust the spring property by tweaking the following values:
- stiffness (tension on the spring, higher value -> faster animation, default: 200)
- damping (friction on the spring, higher value -> less bounciness, default: 10)
- threshold (ending threshold, if both velocity and distance drop below this threshold, the animation is ended, default: 0.01)
The way you adjust these values is like this:
view.animate {
$0.stiffness = 500
$0.damping = 30
$0.threshold = 1
$0.center.target = CGPoint(x:100,y:200) // this animation is affected by the new attributes
$0.bounds.target = CGRect(x:0,y:0,width:100,height:100) // this too
}.animate{
$0.backgroundColor.target = UIColor.black // this is not affected(still uses default stiffness, etc..)
}
Though I believe it is spring is enough for most situations.
I understand that sometimes a timing curve is useful.
(Please let me know if this feature is helpful to you)
By default, all properties(eg. alpha
, center
, backgroundColor
in the example below) are animated concurrently.
view.animate {
$0.alpha.target = 0.5
$0.center.target = CGPoint(x:100,y:200)
}.animate {
$0.backgroundColor.target = UIColor.black
}
Use .then
or .delay(time)
to seperate animations into serial groups.
For example below, alpha
and center
are animated first. Then backgroundColor
. Then bounds
view.animate {
$0.alpha.target = 0.5
$0.center.target = CGPoint(x:100,y:200)
}.then.animate {
$0.backgroundColor.target = UIColor.black
}.then.animate {
$0.bounds.target = CGRect(x:0,y:0,width:100,height:100)
}
view.delay(2).animate {
// this animation is trigger after 2 seconds
$0.alpha.target = 0.5
}.delay(2).animate {
// this animation is trigger after 4 seconds
$0.backgroundColor.target = UIColor.black
}
Use .then{ }
to register callback for animation completion
view.animate {
$0.alpha.target = 0.5
$0.center.target = CGPoint(x:100,y:200)
}.then{
print("First batch done!")
}.animate {
$0.backgroundColor.target = UIColor.black
}.then{
print("Second batch done!")
}
view.animate{
$0.center.target = CGPoint(x:200, y:200)
$0.center.onChange = { newCenter in
print(newCenter)
}
$0.center.onVelocityChange = { velocity in
print("velocity:\(velocity)")
}
}
- frame
- bounds
- center
- backgroundColor
- alpha
- shadowColor
- shadowRadius
- shadowOffset
- shadowOpacity
- transform
- scale
- rotate
- translate
view.animate{
$0.custom(key: "myCustomProperty",
getter: { return view.myCustomProperty.toVec4 },
setter: { nv in view.myCustomProperty = CGFloat.fromVec4(nv) },
target: 100.toVec4 )
}
class GPUAnimator{
func animate(_ item:T,
key:String,
getter:@escaping () -> float4,
setter:@escaping (inout float4) -> Void,
target:float4,
stiffness:Float = 200,
damping:Float = 10,
threshold:Float = 0.01,
completion:((Bool) -> Void)? = nil)
}
// For example
class Foo{
var a:CGFloat = 0
}
var f = Foo()
// Animate f.a to 5
GPUAnimator.sharedInstance.animate(f, key:"a",
getter:{ return f.a.toVec4 },
setter:{ nv in f.a = CGFloat.fromVec4(nv) },
target:5.toVec4)