[翻譯] JHChainableAnimations

JHChainableAnimationshtml

 

 

 

- (void)animationType_01 {
    
    /*
     * 縮放到0.8倍(執行spring動畫效果的縮放)持續時間0.5s,完成了以後移動100的距離持續1s.
     *
     * |<----------------------------  1.5s  ---------------------------->|
     * |                                                                  |
     * |<---      0.5s      -->|                                          |
     * [     scale.spring      ]                                          |
     *                         |<---               1.0s                -->|
     *                         [                  moveXY                  ]
     *
     */
    self.showView.makeScale(0.8f).spring.thenAfter(0.5f).moveXY(100, 0).animateWithCompletion(1.f, JHAnimationCompletion(){
        NSLog(@"動畫完成");
    });;
}

- (void)animationType_02 {
    
    /*
     * 縮放到2倍,移動100的距離同時執行,縮放是普通動畫效果,而移動一百有spring效果
     *
     * |<---                           1.0s                            -->|
     * |                                                                  |
     * [                              scale                               ]
     * [                          moveXY.spring                           ]
     *
     */
    self.showView.makeScale(2.f).moveXY(100, 0).spring.animateWithCompletion(1.f, JHAnimationCompletion(){
        NSLog(@"動畫完成");
    });;
}

- (void)animationType_03 {
    
    /*
     * 縮放到2倍,移動100的距離同時執行,縮放是普通動畫效果,而移動一百有spring效果
     *
     * |<------------------------------------  3.0s  ------------------------------->|
     * |                                                                             |
     * |<---       1.0s       -->|                                                   |
     * [          moveXY         ]                                                   |
     * |                         |<---       1.0s       -->|                         |
     * |                         [           wait          ]                         |
     * |                                                   |<---       1.0s       -->|
     * |                                                   [          moveXY         ]
     */
    self.showView.moveXY(100, 0).thenAfter(1.f).wait(1.f).moveXY(0, 100).animateWithCompletion(1.f, JHAnimationCompletion(){
        NSLog(@"動畫完成");
    });;
}

 

Whats wrong with animations?jquery

CAAnimations and UIView animations are extremely powerful, but it is difficult to chain multiple animations together, especially while changing anchor points.ios

Furthermore, complicated animations are difficult to read.git

CAAnimations以及UIView的動畫很是的強大,可是,若是要實現動畫的組合操做彷佛不大容易,尤爲是要改變anchor點之類的操做.再者,複雜的動畫效果代碼量大,不便於理解與維護.github

Say I want to move myView 50 pixels to the right with spring and then change the background color with inward easing when the movement has finished:objective-c

比方說,我先要向右移動50像素作spring動畫,在移動結束後修改背景色: spring

 

The Old Wayswift

    [UIView animateWithDuration:1.0 delay:0.0 usingSpringWithDamping:0.8 initialSpringVelocity:1.0 options:0 animations:^{ CGPoint newPosition = self.myView.frame.origin; newPosition.x += 50; self.myView.frame.origin = newPosition; } completion:^(BOOL finished) { [UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{ self.myView.backgroundColor = [UIColor purpleColor]; } completion:nil]; }];

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

其實要向上面這麼寫...是否是很噁心.若是用JHChainableAnimations,乙方代碼就搞定,以下.ide

 

The New Way (JHChainableAnimations!!!)

self.myView.moveX(50).spring.thenAfter(1.0).makeBackground([UIColor purpleColor]).easeIn.animate(0.5);

There are also a lot of really good animation libraries out there such as RBBAnimation,DCAnimationKit, and PMTween, but they still fall short of having powerful chainable animations AND easy to read/write syntax.

固然,有着好多很是不錯的動畫庫如 RBBAnimation,DCAnimationKit, 和 PMTween ,可是,他們也不會像我寫的這種使用方式簡單而暴力.

 

Usage

Either clone the repo and manually add the Files in JHChainableAnimations or add the following to your Podfile

你能夠拷貝源碼到你的項目中去,或者是使用Podfile來導入:

pod 'JHChainableAnimations', '~> 1.3.0'

Then just import the following header.

而後引入頭文件.

#import "JHChainableAnimations.h"

This is all a UIView category, so these chainables can be used on any UIView in a file where the header is imported.

全部的文件都是基於UIView的category,因此,你能夠在任何引入頭文件的地方使用.

 

Animating

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

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

鏈表屬性,例如moveX(x)須要在view與animate(t)之間.

view.makeScale(2.0).animate(1.0);

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

若是你想移動view的同時也縮放它,添加另一個鏈表屬性便可.順序不重要.

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

A full list of chainable properties can be found here

一個完整的鏈表屬性能夠在這裏找到.

 

Chaining Animations

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

你須要使用 thenAfter(t) 來分割鏈表動畫.

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.

如下就是一個例子,先縮放0.5秒鐘,而後移動一秒鐘.

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

 

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.

爲了添加動畫效果,你能夠在鏈表屬性以後使用一個效果,以下所示:

view.makeScale(2.0).spring.animate(1.0);

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

若是你添加了2個效果到一個鏈表屬性上去了,只有最後一個會生效.

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

A full list of animation effect properties can be found here

一個完整的動畫效果列表能夠在這裏找到.

 

Anchoring

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

view.rotate(180).anchorTopLeft.thenAfter(1.0).rotate(90).anchorCenter.animate(1.0); // view.rotate(90).anchorTopLeft.anchorCenter == view.rotate(90).anchorCenter

A full list of anchor properties can be found here

 

Delays

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

延時動畫的執行能夠調用 wait(t) 或者 delay(t) 鏈表屬性.

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

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

 

Completion

To run code after an animation finishes set the animationCompletion property of your UIView or call the animateWithCompletion(t, completion) function.

動畫結束後要執行代碼,你能夠設置 animationCompletion 或者調用方法 animateWithCompletion(t, completion)  

view.makeX(0).animateWithCompletion(1.0, JHAnimationCompletion(){ NSLog(@"Animation Done"); });

Is the same as:

view.animationCompletion = JHAnimationCompletion(){
    NSLog(@"Animation Done"); }; view.makeX(0).animate(1.0);

Is the same as:

view.makeX(0).animate(1.0).animationCompletion = JHAnimationCompletion(){ NSLog(@"Animation Done"); };

 

Bezier Paths

You can also animate a view along a UIBezierPath. To get a bezier path starting from the views position, call the bezierPathForAnimation method. Then add points or curves or lines to it and use it in a chainable property.

你也可讓view沿着貝塞爾曲線移動.爲了獲得view的起始移動位置,調用方法 bezierPathForAnimation  便可.而後你在路徑處添加控制點便可.   

UIBezierPath *path = [view bezierPathForAnimation];
[path addLineToPoint:CGPointMake(25, 400)]; [path addLineToPoint:CGPointMake(300, 500)]; view.moveOnPath(path).animate(1.0);

Animation effects do not work on path movements.

 

Semantics

I included a chainable property called seconds that is there purely for show. It does however, make the code a little more readable (if you're into that sort of thing).

view.makeScale(2.0).thenAfter(0.5).seconds.moveX(20).animate(1.0); // view.makeScale(2.0).thenAfter(0.5).moveX(20).animate(1.0);

 

Transforms

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

viewWithConstraints.transformX(50).transformScale(2).animate(1.0);

 

Animating Constraints

Typically frames and autolayout stuff shouldn't mix so use the makeConstraint and moveConstraintchainable properties with caution (i.e dont try and scale a view when it has a height and width constraint). These properties should only be used with color, opacity, and corner radius chainable properties because they dont affect the layers position and therfore won't affect constraints.

This was only added as a syntactically easy way to animate constraints. The code below will set the constant of topConstraint to 50 and then trigger an animated layout pass in the background.

// You have a reference to some constraint for myView
self.topConstraint = [NSLayoutConstraint ...]; ... self.myView.makeConstraint(self.topConstraint, 50).animate(1.0);

This does not support animation effects yet.

 

Using with Swift

Using JHChainableAnimations with Swift is a little different. Every chainable property must have ()between the name and the parameters.

// swift code
view.makeScale()(2.0).spring().animate()(1.0); // is the same as // view.makeScale(2.0).spring.animate(1.0); // in Objective-C

Masonry, which uses a similar chainable syntax eventually made SnapKit to make get rid of this weirdness. That may be on the horizon.

Draveness copied my code into swift and it looks pretty good. DKChainableAnimationKit

 

Chainable Properties

Property Takes a... Usage
- (JHChainableRect) makeFrame; CGRect view.makeFrame(rect).animate(1.0);
- (JHChainableRect) makeBounds; CGRect view.makeBounds(rect).animate(1.0);
- (JHChainableSize) makeSize; (CGFloat: width, CGFloat: height) view.makeSize(10, 20).animate(1.0);
- (JHChainablePoint) makeOrigin; (CGFloat: x, CGFloat: y) view.makeOrigin(10, 20).animate(1.0);
- (JHChainablePoint) makeCenter; (CGFloat: x, CGFloat: y) view.makeCenter(10, 20).animate(1.0);
- (JHChainableFloat) makeX; (CGFloat: f) view.makeX(10).animate(1.0);
- (JHChainableFloat) makeY; (CGFloat: f) view.makeY(10).animate(1.0);
- (JHChainableFloat) makeWidth; (CGFloat: f) view.makeWidth(10).animate(1.0);
- (JHChainableFloat) makeHeight; (CGFloat: f) view.makeHeight(10).animate(1.0);
- (JHChainableFloat) makeOpacity; (CGFloat: f) view.makeOpacity(10).animate(1.0);
- (JHChainableColor) makeBackground; (UIColor: color) view.makeBackground(color).animate(1.0);
- (JHChainableColor) makeBorderColor; (UIColor: color) view.makeBorderColor(color).animate(1.0);
- (JHChainableFloat) makeBorderWidth; (CGFloat: f) view.makeBorderWidth(3.0).animate(1.0);
- (JHChainableFloat) makeCornerRadius; (CGFloat: f) view.makeCornerRadius(3.0).animate(1.0);
- (JHChainableFloat) makeScale; (CGFloat: f) view.makeScale(2.0).animate(1.0);
- (JHChainableFloat) makeScaleX; (CGFloat: f) view.makeScaleX(2.0).animate(1.0);
- (JHChainableFloat) makeScaleY; (CGFloat: f) view.makeScaleY(2.0).animate(1.0);
- (JHChainablePoint) makeAnchor; (CGFloat: x, CGFloat: y) view.makeAnchor(0.5, 0.5).animate(1.0);
- (JHChainableFloat) moveX; (CGFloat: f) view.moveX(50).animate(1.0)
- (JHChainableFloat) moveY; (CGFloat: f) view.moveY(50).animate(1.0)
- (JHChainablePoint) moveXY; (CGFloat: x, CGFloat: y) view.moveXY(100, 50).animate(1.0)
- (JHChainableFloat) moveHeight; (CGFloat: f) view.moveHeight(50).animate(1.0)
- (JHChainableFloat) moveWidth; (CGFloat: f) view.moveWidth(50).animate(1.0)
- (JHChainableDegrees) rotate; (CGFloat: angle) #not radians! view.rotate(360).animate(1.0);
- (JHChainablePolarCoordinate) movePolar; (CGFloat: radius, CGFloat: angle) view.movePolar(30, 90).animate(1.0);
- (JHChainableBezierPath) moveOnPath; (UIBezierPath *path) view.moveOnPath(path).animate(1.0);
- (JHChainableBezierPath) moveAndRotateOnPath; (UIBezierPath *path) view.moveAndRotateOnPath(path).animate(1.0);
- (JHChainableBezierPath) moveAndReverseRotateOnPath; (UIBezierPath *path) view.moveAndReverseRotateOnPath(path).animate(1.0);
- (JHChainableFloat) transformX; (CGFloat f) view.transformX(50).animate(1.0);
- (JHChainableFloat) transformX; (CGFloat f) view.transformX(50).animate(1.0);
- (JHChainableFloat) transformY; (CGFloat f) view.transformY(50).animate(1.0);
- (JHChainableFloat) transformZ; (CGFloat f) view.transformZ(50).animate(1.0);
- (JHChainablePoint) transformXY; (CGFloat x, CGFloat y) view.transformXY(50, 100).animate(1.0);
- (JHChainableFloat) transformScale; (CGFloat f) view.transformScale(50).animate(1.0);
- (JHChainableFloat) transformScaleX; (CGFloat f) view.transformScaleX(50).animate(1.0);
- (JHChainableFloat) transformScaleY; (CGFloat f) view.transformScaleY(50).animate(1.0);
- (UIView *) transformIdentity; Nothing view.transformIdentity.animate(1.0);

 

Animation Effects

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

 

Anchoring

Info on anchoring can be found here

To Do

I have gotten a ton of great suggestions of what to do next. If you think this is missing anything please let me know! The following is what I plan on working on in no particular order.

  • OSX port

 

Contact Info && Contributing

Feel free to email me at jhurray33@gmail.com. I'd love to hear your thoughts on this, or see examples where this has been used.

MIT License

相關文章
相關標籤/搜索