⛓ Easy to Read and Write Multi-chain Animations Lib in Objective-C and Swift.


language  language  CocoaPods  Carthage compatible  Build Status  License MIT  CocoaPods  Support


This project is inspired by JHChainableAnimations!

Why Choose LSAnimator & CoreAnimator?

You can write complex and easy-to-maintain animations in just a few lines of code by use LSAnimator(Objective-C) or CoreAnimator(Swift).

Objective-C  Swift

What's The Multi-chain Animations?

CAAnimations and UIView animations are extremely powerful, but it is very hard to read when the animation is complicated.

Say I want to move myView 100 pixels to the right with spring and then incre 30 pixels to the width with inward easing when the movement has finished:

The Old Way

[UIView animateWithDuration:2.0
                         CGPoint newPosition = self.myView.frame.origin;
                         newPosition.x += 100;
                         self.myView.frame = CGRectMake(newPosition.x, newPosition.y, self.myView.frame.size.width, self.myView.frame.size.height);
                     } completion:^(BOOL finished) {
                         [UIView animateWithDuration:2.0
                                              CGSize newSize = self.myView.frame.size;
                                              newSize.width += 30;
                                              self.myView.frame = CGRectMake(self.myView.frame.origin.x, self.myView.frame.origin.y, newSize.width, newSize.height);
                                          } completion:nil];

Thats pretty gross huh... With LSAnimator it is one line of code.

Using LSAnimator

LSAnimator *animator = [LSAnimator animatorWithView:self.myView];

Emmmmm...There is an animation library called JHChainableAnimations can also do this.

Whats wrong with JHChainableAnimations?

JHChainableAnimations has powerful chainable animations AND easy to read/write syntax, but it does not support for Multi-chain Animations.

Following the example above, assume now that the whole animation chain above needs to change the transparency of myView to zero at the same time:

Using LSAnimator


With LSAnimator it is just need to add one line of code.

LSAnimator *animator = [LSAnimator animatorWithView:self.myView];

Using JHChainableAnimations


Emmmmm...With JHChainableAnimations it is can not finished task. Trying to add the following code will cause the animation bug or crash.

JHChainableAnimator *animator = [[JHChainableAnimator alloc] initWithView:self.myView];

LSAnimator VS JHChainableAnimations

  • Multi-chain Animations: Can complete all animation design needs, More flexible than JHChainableAnimations.
  • CALayer Support: Support CALayer initialization, JHChainableAnimations only supports UIView.
  • Parameter Auto-completion: Support parameter auto-completion, JHChainableAnimations does not support.

LSAnimator support parameter auto-completion, including the number of parameters and parameter types:


JHChainableAnimations is not friendly when actually writing code.


JHChainableAnimations is still a really good animation library and LSAnimator is standing on the shoulders of it.


  • Swift Support: Swift 3.2 ~ 4 Support.
  • Friendly Swift Interface: Added friendly Swift interface in separate framework.
  • Multi-chain Animations: Can complete all animation design needs.
  • CALayer Support: Support CALayer initialization.
  • Parameter Auto-completion: Support parameter auto-completion.
  • Support for Animation Hooks: Added pre-animation and post-animation hooks for each animation step. Added a final completion hook that fires when all animation chains have completed.
  • Non-intrusive: There is no need to make the view/layer class inherit from other base class.


Creating an Animator

// UIView initialization
LSAnimator *viewAnimator = [LSAnimator animatorWithView:self.myView];
LSAnimator *viewAnimator = [[LSAnimator alloc] initWithView:self.myView];

// CALayer initialization
LSAnimator *layerAnimator = [LSAnimator animatorWithLayer:self.myLayer];
LSAnimator *layerAnimator = [[LSAnimator alloc] initWithLayer:self.myLayer];


Chainable properties like moveX(x) must come between the animator and the animate(t) function.

Below is an example of how to double an objects size over the course of one second.


Combining Animations

If you want to move the view while you scale it, add another chainable property. Order is not important.

animator.makeScale(2.0).moveXY(100, 50).animate(1.0);
// the same as animator.moveXY(100, 50).makeScale(2.0).animate(1.0);

Note: Combining Animations works only for the animation that needs to be done in the same step.

If the animations have different durations. When they can not be done in the same animation step, they need to use Multi-chain Animations.

A full list of chainable properties can be found here.

Chaining Animations

To chain animations seperate the chains with the thenAfter(t) function.

Below is an example of how to scale and object for 0.5 seconds, and then move it for 1 second when that is done.

animator.makeScale(2.0).thenAfter(0.5).moveXY(100, 50).animate(1.0);

Animation Effects

Animation Effects To add an animation effect, call the effect method after the chainable property you want it to apply to.

Below is an example of scaling a view with a spring effect.


If you add 2 to the same chainable property the second will cancel the first out.

// The same as animator.makeScale(2.0).spring.animate(1.0);

A full list of animation effect properties can be found here.


To anchor your view call an achoring method at some point in an animation chain. Like effects, calling one after another in the same chain will cancel the first out.

Below is an example of rotating a view around different anchor points.

// animator.rotateZ(90).anchorTopLeft.anchorCenter == animator.rotateZ(90).anchorCenter

A full list of anchor properties can be found here.


To delay an animation call the wait(t) or delay(t) chainable property.

Below is an example of moving a view after a delay of 0.5 seconds.

animator.moveXY(100, 50).wait(0.5).animate(1.0);
// The same as animator.moveXY(100, 50).delay(0.5).animate(1.0);


To run code after an animation finishes call the animateWithCompletion(t, completion)* function.

animator.makeX(0).animateWithCompletion(1.0, ^{
	NSLog(@"Animation Done");

Repeating Animations

You can repeat an animation by replacing the thenAfter(time) method with the repeat(time, count) method. This will repeat the previously defined animations.

animator.increWidth(30).spring.repeat(0.5, 3).moveXY(100, 50).animate(1.0);

You can repeat the last part of an animation by calling animateWithRepeat(time, count).

animator.increWidth(30).spring.animateWithRepeat(0.5, 3);


You can hook into the different steps of the animation process by calling the preAnimationBlock(block) and postAnimationBlock(block) methods. All take a simple block void(^block)(void) as an argument. Order of calling these in the animation chain does not matter.

    NSLog(@"before the first animation");
    NSLog(@"After the second animation");

Bezier Paths

You can also animate a view along a UIBezierPath. Create a UIBezierPath * instance, then add points or curves or lines to it and use it in a chainable property.

UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:self.myView.center];
[path addLineToPoint:CGPointMake(25, 400)];
[path addLineToPoint:CGPointMake(300, 500)];

Using with Auto Layout


Use the transform chainable properties. These are better for views constrained with Autolayout. You should not mix these with other chainable properties.


Using with Swift

Using LSAnimator with Swift is now a little more readable in version 2.x. I created a separate framework for swift that provides a class called CoreAnimator. This is a thin wrapper over LSAnimator that has a slightly more readable syntax.

let animator = CoreAnimator(view: myView)
animator.move(x: 60).thenAfter(t: 1.0).rotate(angle: 360).bounce.animate(t: 1.0)

Chainable Properties

#pragma mark - Animations
// Makes
// Affects views position and bounds
@property (nonatomic, copy, readonly) LSAnimatorRect makeFrame;
@property (nonatomic, copy, readonly) LSAnimatorRect makeBounds;
@property (nonatomic, copy, readonly) LSAnimatorSize makeSize;
@property (nonatomic, copy, readonly) LSAnimatorPoint makeOrigin;
@property (nonatomic, copy, readonly) LSAnimatorPoint makePosition;
@property (nonatomic, copy, readonly) LSAnimatorFloat makeX;
@property (nonatomic, copy, readonly) LSAnimatorFloat makeY;
@property (nonatomic, copy, readonly) LSAnimatorFloat makeWidth;
@property (nonatomic, copy, readonly) LSAnimatorFloat makeHeight;
@property (nonatomic, copy, readonly) LSAnimatorFloat makeOpacity;
@property (nonatomic, copy, readonly) LSAnimatorColor makeBackground;
@property (nonatomic, copy, readonly) LSAnimatorColor makeBorderColor;
@property (nonatomic, copy, readonly) LSAnimatorFloat makeBorderWidth;
@property (nonatomic, copy, readonly) LSAnimatorFloat makeCornerRadius;
@property (nonatomic, copy, readonly) LSAnimatorFloat makeScale;
@property (nonatomic, copy, readonly) LSAnimatorFloat makeScaleX;
@property (nonatomic, copy, readonly) LSAnimatorFloat makeScaleY;
@property (nonatomic, copy, readonly) LSAnimatorPoint makeAnchor;

// Moves
// Affects views position and bounds
@property (nonatomic, copy, readonly) LSAnimatorFloat moveX;
@property (nonatomic, copy, readonly) LSAnimatorFloat moveY;
@property (nonatomic, copy, readonly) LSAnimatorPoint moveXY;
@property (nonatomic, copy, readonly) LSAnimatorPolarCoordinate movePolar;

// Increments
// Affects views position and bounds
@property (nonatomic, copy, readonly) LSAnimatorFloat increWidth;
@property (nonatomic, copy, readonly) LSAnimatorFloat increHeight;
@property (nonatomic, copy, readonly) LSAnimatorSize increSize;

// Transforms
// Affects views transform property NOT position and bounds
// These should be used for AutoLayout
// These should NOT be mixed with properties that affect position and bounds
- (LSAnimator *)transformIdentity;
@property (nonatomic, copy, readonly) LSAnimatorDegrees rotate; // Same as rotateZ
@property (nonatomic, copy, readonly) LSAnimatorDegrees rotateX;
@property (nonatomic, copy, readonly) LSAnimatorDegrees rotateY;
@property (nonatomic, copy, readonly) LSAnimatorDegrees rotateZ;
@property (nonatomic, copy, readonly) LSAnimatorFloat transformX;
@property (nonatomic, copy, readonly) LSAnimatorFloat transformY;
@property (nonatomic, copy, readonly) LSAnimatorFloat transformZ;
@property (nonatomic, copy, readonly) LSAnimatorPoint transformXY;
@property (nonatomic, copy, readonly) LSAnimatorFloat transformScale; // x and y equal
@property (nonatomic, copy, readonly) LSAnimatorFloat transformScaleX;
@property (nonatomic, copy, readonly) LSAnimatorFloat transformScaleY;

#pragma mark - Bezier Paths
// Animation effects dont apply
@property (nonatomic, copy, readonly) LSAnimatorBezierPath moveOnPath;
@property (nonatomic, copy, readonly) LSAnimatorBezierPath moveAndRotateOnPath;
@property (nonatomic, copy, readonly) LSAnimatorBezierPath moveAndReverseRotateOnPath;

Animation Effects

- (LSAnimator *)easeIn;
- (LSAnimator *)easeOut;
- (LSAnimator *)easeInOut;
- (LSAnimator *)easeBack;
- (LSAnimator *)spring;
- (LSAnimator *)bounce;
- (LSAnimator *)easeInQuad;
- (LSAnimator *)easeOutQuad;
- (LSAnimator *)easeInOutQuad;
- (LSAnimator *)easeInCubic;
- (LSAnimator *)easeOutCubic;
- (LSAnimator *)easeInOutCubic;
- (LSAnimator *)easeInQuart;
- (LSAnimator *)easeOutQuart;
- (LSAnimator *)easeInOutQuart;
- (LSAnimator *)easeInQuint;
- (LSAnimator *)easeOutQuint;
- (LSAnimator *)easeInOutQuint;
- (LSAnimator *)easeInSine;
- (LSAnimator *)easeOutSine;
- (LSAnimator *)easeInOutSine;
- (LSAnimator *)easeInExpo;
- (LSAnimator *)easeOutExpo;
- (LSAnimator *)easeInOutExpo;
- (LSAnimator *)easeInCirc;
- (LSAnimator *)easeOutCirc;
- (LSAnimator *)easeInOutCirc;
- (LSAnimator *)easeInElastic;
- (LSAnimator *)easeOutElastic;
- (LSAnimator *)easeInOutElastic;
- (LSAnimator *)easeInBack;
- (LSAnimator *)easeOutBack;
- (LSAnimator *)easeInOutBack;
- (LSAnimator *)easeInBounce;
- (LSAnimator *)easeOutBounce;
- (LSAnimator *)easeInOutBounce;

A quick look at these funcs can be found here

These animation functions were taken from a cool keyframe animation library that can be found here

They are based off of JQuery easing functions that can be found here


- (LSAnimator *)anchorDefault;
- (LSAnimator *)anchorCenter;
- (LSAnimator *)anchorTop;
- (LSAnimator *)anchorBottom;
- (LSAnimator *)anchorLeft;
- (LSAnimator *)anchorRight;
- (LSAnimator *)anchorTopLeft;
- (LSAnimator *)anchorTopRight;
- (LSAnimator *)anchorBottomLeft;
- (LSAnimator *)anchorBottomRight;

Multi-chain Animations

You can add a new animation chain by calling the concurrency method. It does not affect the previous animation chains.

animator.increWidth(20).spring.animateWithRepeat(0.5, 3);
animator.concurrent.makeBackground([UIColor orangeColor]).animate(1);

Do not change the properties of the animation chain before the new animation chain operates at the same time.

// Do not do this

To Do

  • Constraint animator




  1. Add pod 'LSAnimator', '~> 2.1.5' to your Podfile.
  2. Run pod install or pod update.
  3. Add #import <LSAnimator/LSAnimator.h>.


  1. Add pod 'CoreAnimator', '~> 2.1.5' to your Podfile.
  2. Run pod install or pod update.
  3. Add import CoreAnimator.


  1. Add github "Lision/LSAnimator" ~> 2.1.5 to your Cartfile.
  2. Run carthage update --platform ios.


Add the LSAnimator framework to your project.


Add the CoreAnimator framework to your project.


Either clone the repo and manually add the Files in LSAnimator


  • LSAnimator requires iOS 7.0+.
  • CoreAnimator requires iOS 9.0+.



LSAnimator is provided under the MIT license. See LICENSE file for details.

  • 关于JHChainableAnimator 的组合动画

    关于JHChainableAnimator 的组合动画

    看了下你的Blog,你执行了2遍animate,所以是后面冲掉前面的animation了 这种情况你只要执行第2个animate, 第一个animate去掉,就是个组合动画。 JHChainableAnimator *animator = [[JHChainableAnimator alloc] initWithView:_animatorView]; animator.makeCornerRadius(20).thenAfter(2).moveY(100); animator.makeOpacity(0).animate(4); JHChainableAnimator 是能做组合动画的,你举的例子代码写的不对。


    opened by Eflet 6
  • 关于 force_inline的疑问

    关于 force_inline的疑问

    您好,在您的代码中有一个强制内联的函数 static force_inline NSString *LSAnimatorChainAnimationKey(NSInteger index) { return [NSString stringWithFormat:@"%@_%@", kLSAnimatorKey, @(index)]; } 这里我有一个疑问,为什么要强制内联呢?非常期待您的回复

    opened by RSComponent 4
  • Regarding making animation to original position

    Regarding making animation to original position

    lets say i have make animation like myview.animation.moveX(60).animationCompletion = {

    //how do i make it to identity like we do in default UIView.animation block

    myview.transform = .identity }

    is there a method to make the animation come to its original position after animation completed

    opened by text4lilac 0
  • 这种重复动画咋写?



        LSAnimator * ani = [LSAnimator animatorWithView:self.handView];
        ani.moveXY(-20, -20).postAnimationBlock(^{
            [self endFingerAni];
        LSAnimator * ani = [LSAnimator animatorWithView:self.handView];
        ani.moveXY(20, 20).postAnimationBlock(^{
            [self startFingerAni];


    opened by vitasapple 0
  • CAKeyframeAnimation动画怎么搞?



        CAKeyframeAnimation * anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
        anim.values = @[[NSValue valueWithCGPoint:CGPointMake(targetV.center.x, targetV.center.y)],
                        [NSValue valueWithCGPoint:CGPointMake(targetV.center.x, targetV.center.y + 1)],
                        [NSValue valueWithCGPoint:CGPointMake(targetV.center.x+1, targetV.center.y - 1)],
                        [NSValue valueWithCGPoint:CGPointMake(targetV.center.x-1, targetV.center.y + 1)]];
        anim.duration = 0.2;
        anim.repeatCount = 5;
        anim.removedOnCompletion = YES;
        [targetV.layer addAnimation:anim forKey:@"shake"];
    opened by vitasapple 0
  • Param Auto-Complete Fail

    Param Auto-Complete Fail

    animator.makeX(10).preAnimationBlock(^{ NSLog(@""); }).makeSize

    with anything written in block will result in param auto-complete fail

    it should be sth like following


    }).makeSize(<#CGFloat width#>, <#CGFloat height#>)
    opened by sanshanchuns 0
Easy to read and write chainable animations in Objective-C and Swift

Whats new in version 3.x? Swiftier syntax Swift 4 support Bug fixes and improvements Whats new in version 2.x? Re-architected from the ground up, no m

Jeff Hurray 3.2k Nov 20, 2022
(Animate CSS) animations for iOS. An easy to use library of iOS animations. As easy to use as an easy thing.

wobbly See Wobbly in action (examples) Add a drop of honey ?? to your project wobbly has a bunch of cool, fun, and easy to use iOS animations for you

Sagaya Abdulhafeez 150 Dec 23, 2021
(Animate CSS) animations for iOS. An easy to use library of iOS animations. As easy to use as an easy thing.

wobbly See Wobbly in action (examples) Add a drop of honey ?? to your project wobbly has a bunch of cool, fun, and easy to use iOS animations for you

Sagaya Abdulhafeez 150 Dec 23, 2021
Chain multiple UIView animations without endlessly nesting in completion closures.

⛓ Chain multiple UIView animations without endlessly nesting in completion closures. Used in some of the more superfluous animations in the OK Video app.

Pim 73 Nov 15, 2022
A concept to more easily define simple keyframe / multi-step animations in SwiftUI

?? Animate A concept to more easily define simple keyframe / multi-step animations in SwiftUI, without: Defining an @State value for each property to

Seb Jachec 3 Oct 18, 2022
A collection of animations for iOS. Simple, just add water animations.

DCAnimationKit A collection of animations for iOS Simply, just add water! DCAnimationKit is a category on UIView to make animations easy to perform. E

Dalton 797 Sep 23, 2022
Circular reveal animations made easy

This library was created to allow developers to implement the material design's reveal effect. You can simply use this component to reveal and unverea

T-Pro 24 Jun 22, 2021
Wave is a spring-based animation engine for iOS that makes it easy to create fluid, interruptible animations that feel great.

Wave is a spring-based animation engine for iOS and iPadOS. It makes it easy to create fluid, interactive, and interruptible animations that feel great.

Janum Trivedi 1.1k Nov 16, 2022
This repo contains swift collection of gui, games, menu, animations, music, payment, etc... for iOS, macOS, watchOS and tvOS

Swift-Collections About: This repo contains a collection of projects built using swift and objective-c Contains projects for macOS iOS iPad watchOS tv

Krisna Pranav 6 Nov 15, 2022
Swift interpolation for gesture-driven animations

Interpolate Interpolate is a powerful Swift interpolation framework for creating interactive gesture-driven animations. Usage The ?? idea of Interpola

Roy Marmelstein 1.8k Nov 3, 2022
A library to simplify iOS animations in Swift.

Updated for Swift 4.2 Requires Xcode 10 and Swift 4.2. Installation Drop in the Spring folder to your Xcode project (make sure to enable "Copy items i

Meng To 14k Nov 16, 2022
Swift library for choreographing animations on the screen.

Spruce iOS Animation Library (and Android) What is it? Spruce is a lightweight animation library that helps choreograph the animations on the screen.

WillowTree, LLC 3.3k Nov 19, 2022
Composable animations in Swift

Composable animations in Swift. Blog Installation Cocoapods The easiest way to get started is to use CocoaPods. Just add the following line to your Po

Reid Chatham 196 Sep 1, 2022
SamuraiTransition is an open source Swift based library providing a collection of ViewController transitions featuring a number of neat “cutting” animations.

SamuraiTransiton is a ViewController transition framework in Swift. It is an animation as if Samurai cut out the screen with a sword. transition types

hachinobu 274 Oct 19, 2022
Declarative chainable animations in Swift

Wave Declarative chainable animations in Swift ❤️ Support my apps ❤️ Push Hero - pure Swift native macOS application to test push notifications PasteP

Khoa 125 Oct 10, 2022
Physics-based animations for iOS, tvOS, and macOS.

Advance An animation library for iOS, tvOS, and macOS that uses physics-based animations (including springs) to power interactions that move and respo

Tim Donnelly 4.5k Nov 17, 2022
A library of custom iOS View Controller Animations and Interactions.

RZTransitions is a library to help make iOS7 custom View Controller transitions slick and simple. Installation CocoaPods (Recommended) Add the followi

Rightpoint 1.9k Nov 20, 2022
Match animations in SwiftUI and UIKit/AppKit

MatchedAnimation Match animations in SwiftUI and UIKit/AppKit. /// Draw a box in

Ryan Carver 4 Oct 31, 2022