Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/lkzhao/yetanotheranimationlibrary
Designed for gesture-driven animations. Fast, simple, & extensible!
https://github.com/lkzhao/yetanotheranimationlibrary
Last synced: 3 days ago
JSON representation
Designed for gesture-driven animations. Fast, simple, & extensible!
- Host: GitHub
- URL: https://github.com/lkzhao/yetanotheranimationlibrary
- Owner: lkzhao
- License: mit
- Created: 2017-04-08T20:18:27.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2023-10-08T23:08:02.000Z (about 1 year ago)
- Last Synced: 2024-04-30T19:22:24.248Z (8 months ago)
- Language: Swift
- Homepage:
- Size: 352 KB
- Stars: 516
- Watchers: 10
- Forks: 29
- Open Issues: 7
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Yet Another Animation Library
Designed for gesture-driven animations. Fast, simple, & extensible!
It is written in pure swift 3.1 with protocol oriented design and extensive use of generics.
Consider this as a swift optimized version of facebook's pop. It plays nicer with swift and faster too.
**Fast**:
* Uses SIMD types and instructions for calculation
* Better compiler optimization through swift generics**Simple**:
* Supports Curve(Basic), Spring, & Decay animations out of the box
* Easy API for animating common animatable properties. (checkout the [Extensions](https://github.com/lkzhao/YetAnotherAnimationLibrary/tree/master/Sources/Extensions) folder for list of included properties)
* Type safety guaranteed when assigning animation values
* Observable, including value, velocity, and target value
* Builtin chaining operator to easily react to changes in value
* Provide velocity interpolation with gestures**Extensible**:
* Supports custom property
* Supports custom animatable type
* Supports custom animation## Installation
```ruby
pod "YetAnotherAnimationLibrary"
```## Usage
### Animation
```swift
// Spring animation
view.yaal.center.animateTo(CGPoint(x:50, y:100))
view.yaal.alpha.animateTo(0.5, stiffness: 300, damping: 20)// Curve(Basic) animation
view.yaal.frame.animateTo(CGRect(x:0, y:0, width:50, height:50), duration:0.5, curve: .linear)// Decay Animation
view.yaal.center.decay(initialVelocity:CGPoint(x:100, y:0))
```### Observe Changes
```swift
// observe value changes
view.yaal.center.value.changes.addListener { oldVelocity, newVelocity in
print(oldVelocity, newVelocity)
}
// observe velocity changes
view.yaal.center.velocity.changes.addListener { oldVelocity, newVelocity in
print(oldVelocity, newVelocity)
}
```### Chaining Reactions
```swift
// when scale changes, also change its alpha
// for example if view's scale animates from 1 to 0.5. its alpha will animate to 0.5 as well
view.yaal.scale.value => view.yaal.alpha
// equvalent to the following
// view.yaal.scale.value.changes.addListener { _, newScale in
// view.yaal.alpha.animateTo(newScale)
// }// optionally you can provide a mapping function in between.
// For example, the following code makes the view more transparent the faster it is moving
view.yaal.center.velocity => { 1 - $0.magnitude / 1000 } => view.yaal.alpha
// equvalent to the following
// view.yaal.center.velocity.changes.addListener { _, newVelocity in
// view.yaal.alpha.animateTo(1 - newVelocity.magnitude / 1000)
// }
```### Set Value (Notify listeners)
```swift
// this sets the value directly (not animate to). Change listeners are called.
// Velocity listeners will receive a series of smoothed velocity values.
view.yaal.center.setTo(gestureRecognizer.location(in:nil))
```## Advance Usages
### React to changes
Animate is very efficient at observing animated value and react accordingly. Some awesome effects can be achieved through observed values.For example, here is a simple 2d rotation animation thats made possible through observing the center value's velocity.
```swift
override func viewDidLoad() {
// ...
view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tap(gr:))))
squareView.yaal.center.velocity => { $0.x / 1000 } => squareView.yaal.rotation
}
func tap(gr: UITapGestureRecognizer) {
squareView.yaal.center.animateTo(gr.location(in: view))
}
```----------------------
Animate also provide smooth velocity interpolation when calling `setTo(_:)`. This is especially useful when dealing with user gesture.
For example. the following does a 3d rotate animation when dragged
```swift
override func viewDidLoad() {
// ...
squareView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(pan(gr:))))
squareView.yaal.perspective.setTo(-1.0 / 500.0)
squareView.yaal.center.velocity => { $0.x / 1000 } => squareView.yaal.rotationY
squareView.yaal.center.velocity => { -$0.y / 1000 } => squareView.yaal.rotationX
}func pan(gr: UIPanGestureRecognizer) {
squareView.yaal.center.setTo(gr.location(in: view))
}
```### Custom property
To animate custom property, just create an animation object by calling `SpringAnimation(getter:setter:)`. Use the animation object to animate and set the values. There are 4 types of animations provided by Animate:
* SpringAnimation
* CurveAnimation
* DecayAnimation
* MixAnimation (does all three types of animation)```swift
class Foo {
var volumn: Float = 0.0
lazy var volumnAnimation: SpringAnimation
= SpringAnimation(getter: { [weak self] in self?.volumn },
setter: { [weak self] in self?.volumn = $0 })
}volumnAnimation.animateTo(0.5)
```If your class inherits from NSObject, then it is even easier by using the built in animation store.
### via extension & `yaal.animationFor`
```swift
extension Foo {
public var volumnAnimation: MixAnimation {
return yaal.animationFor(key: "volumn",
getter: { [weak self] in self?.volumn },
setter: { [weak self] in self?.volumn = $0 })
}
}
```### via `yaal.register` & `yaal.animationFor`
```swift
// or register ahead of time
yaal.register(key: "volumn",
getter: { [weak self] in self?.volumn },
setter: { [weak self] in self?.volumn = $0 })// and retrieve the animation object through the same key.
yaal.animationFor(key: "volumn")!.animateTo(0.5)// NOTE: that this method have limited type safety. You can basically pass any animatable type into `animateTo()`
// There is nothing to stop you from doing the following. but they will crash at run time
yaal.animationFor(key: "volumn")!.animateTo(CGSize.zero)
yaal.animationFor(key: "volumn")!.animateTo(CGRect.zero)
```### Custom Animatable Type
Custom animatable types are also supported. Just make the type conform to `VectorConvertable`.
```swift
// the following makes IndexPath animatable
extension IndexPath: VectorConvertible {
public typealias Vector = Vector2
public init(vector: Vector) {
self.init(item: Int(vector.x), section: Int(vector.y))
}
public var vector: Vector {
return [Double(item), Double(section)]
}
}
// Can now be used like this
let indexAnimation = SpringAnimation(getter: { self.indexPath },
setter: { self.indexPath = $0 })
indexAnimation.animateTo(IndexPath(item:0, section:0))// Note that everything is type safe. incorrect type won't be allowed to compile
```### Custom Animation
Just subclass `Animation` and override `update(dt:TimeInterval)` method.
If your animation need getter & setter support, subclass `ValueAnimation` instead.
Checkout the builtin animations for example.