JHChainableAnimations

简介:

JHChainableAnimations

 

 

 

- (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?

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

Furthermore, complicated animations are difficult to read.

CAAnimations以及UIView的动画非常的强大,但是,如果要实现动画的组合操作似乎不大容易,尤其是要改变anchor点之类的操作.再者,复杂的动画效果代码量大,不便于理解与维护.

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:

比方说,我先要向右移动50像素做spring动画,在移动结束后修改背景色: 

 

The Old Way

    [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.

其实要向上面这么写...是不是很恶心.如果用JHChainableAnimations,乙方代码就搞定,如下.

 

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

目录
相关文章
|
6月前
|
开发工具 git
Git从远程仓库拉取指定的分支
Git从远程仓库拉取指定的分支
1131 0
|
Swift iOS开发 Perl
如何解决Swift混编的module编译错误
前言很多iOS工程都是基于Object-C开发,再逐步向Swift演进,演进过程中不可避免要进行Swift混编。Swift模块需要支持LLVM Module规范,混编工程会遇到各种Module编译错误。这对于不熟悉的同学来说简直是灾难,严重影响开发效率。本文会介绍常见的Module编译错误,希望对大家有所帮助。常见错误1:Could not build module xxx当一个OC模块引用了Sw
6291 1
如何解决Swift混编的module编译错误
|
3月前
|
iOS开发 Perl
解决Xcode15报错:DT_TOOLCHAIN_DIR cannot be used to evaluate LIBRARY_SEARCH_PATHS
解决Xcode15报错:DT_TOOLCHAIN_DIR cannot be used to evaluate LIBRARY_SEARCH_PATHS
168 1
|
测试技术 程序员 Linux
手把手教你用Git——详解git merge
手把手教你用Git——详解git merge
7514 0
|
网络协议 安全 Linux
如何修复 SSH Client_loop: send disconnect: Broken pipe Error
如何修复 SSH Client_loop: send disconnect: Broken pipe Error
3257 1
|
2天前
|
人工智能 自动驾驶 大数据
预告 | 阿里云邀您参加2024中国生成式AI大会上海站,马上报名
大会以“智能跃进 创造无限”为主题,设置主会场峰会、分会场研讨会及展览区,聚焦大模型、AI Infra等热点议题。阿里云智算集群产品解决方案负责人丛培岩将出席并发表《高性能智算集群设计思考与实践》主题演讲。观众报名现已开放。
|
19天前
|
存储 人工智能 弹性计算
阿里云弹性计算_加速计算专场精华概览 | 2024云栖大会回顾
2024年9月19-21日,2024云栖大会在杭州云栖小镇举行,阿里云智能集团资深技术专家、异构计算产品技术负责人王超等多位产品、技术专家,共同带来了题为《AI Infra的前沿技术与应用实践》的专场session。本次专场重点介绍了阿里云AI Infra 产品架构与技术能力,及用户如何使用阿里云灵骏产品进行AI大模型开发、训练和应用。围绕当下大模型训练和推理的技术难点,专家们分享了如何在阿里云上实现稳定、高效、经济的大模型训练,并通过多个客户案例展示了云上大模型训练的显著优势。
|
22天前
|
存储 人工智能 调度
阿里云吴结生:高性能计算持续创新,响应数据+AI时代的多元化负载需求
在数字化转型的大潮中,每家公司都在积极探索如何利用数据驱动业务增长,而AI技术的快速发展更是加速了这一进程。
|
13天前
|
并行计算 前端开发 物联网
全网首发!真·从0到1!万字长文带你入门Qwen2.5-Coder——介绍、体验、本地部署及简单微调
2024年11月12日,阿里云通义大模型团队正式开源通义千问代码模型全系列,包括6款Qwen2.5-Coder模型,每个规模包含Base和Instruct两个版本。其中32B尺寸的旗舰代码模型在多项基准评测中取得开源最佳成绩,成为全球最强开源代码模型,多项关键能力超越GPT-4o。Qwen2.5-Coder具备强大、多样和实用等优点,通过持续训练,结合源代码、文本代码混合数据及合成数据,显著提升了代码生成、推理和修复等核心任务的性能。此外,该模型还支持多种编程语言,并在人类偏好对齐方面表现出色。本文为周周的奇妙编程原创,阿里云社区首发,未经同意不得转载。