iOS动画(二) - UIKit Dynamics动力系统

1.什么是动力系统(What is the UIKit Dynamics?)

动力系统的引入,并不是替代CoreAnimation,而是对模拟现实世界物体运动的补充,比如,碰撞,重力,悬挂等等。所以说,UIKit动力系统的引入,大大简化了一些交互动画(不需要自己实现一些模拟现实世界物理动力系统的动画),丰富了UI设计。

2.动力系统怎么使用(How to use it?)

UIKit动力系统结构如下:

image

总的来说,先要注册UI系统体系,也就是类似于二维的坐标系,然后添加所需的行为以及行为的作用物体,然后该物体就能在设定的坐标体系里,根据所添加的行为运动。

光说不练乃是纸上谈兵,没有成效。下面分解动力系统所包含的几类运动。

UIGravityBehavior

重力,这个大家应该都很熟悉了。我们每天都能感受到它的存在,所谓脚踏实地就是这种感觉。小时候,大家应该都有过从高处把一些物体扔下来,或者直接让它坐自由落体运动,相似的,这个Gravity也是模拟重力行为,下面直接上代码。

myAnimator = [[UIDynamicAnimator alloc] initWithReferenceView: self];
myAnimator.delegate = self;
UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems: @[ball]];
[myAnimator addBehavior: gravityBehavior];

1.UIDynamicAnimator就是一个播放者,容器。一个容纳动力系统的环境,而referenceView就是该环境的坐标系,物体运动的参照系。

  1. gravityBehavior,初始化一个重力行为,行为的受力物体是ball(只要实现UIDynamicItem接口的类都能作为受力物体,如,View和UICollectionViewLayoutAttributes)。
  2. 将这个行为添加到UIDynamicAnimator上面就行了。
  3. 显示效果的Demo以及代码下载在最后。

UICollisionBehavior

碰撞行为,最直接的感受就是,玩弹珠,一颗弹珠可以被另一颗弹珠弹射到很远的地方,原理就是碰撞产生了一个反方向的作用力,远离事故发生地。废话也不多说,直接上代码:

myAnimator = [[UIDynamicAnimator alloc] initWithReferenceView: self];

UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems: ballsArray2];        collision.translatesReferenceBoundsIntoBoundary = YES;
collision.collisionDelegate = self;
[myAnimator addBehavior: collision];

1.和重力行为一样,也要先初始化一个容器myAnimator。

2.添加碰撞行为collision,collision.translatesReferenceBoundsIntoBoundary的属性是否设置以参考View的边界为碰撞边界,我们这里选择YES。

3.除了设置参考View的边界为碰撞边界外,还可以自己设定边界,使用- addBoundaryWithIdentifier: forPath:或者addBoundaryWithIdentifier: fromPoint: toPoint:方法可以自己设定碰撞边界的范围。
4。最后,也需要把collision添加到myAnimator上。

UIAttachmentBehavior

描述一个物体和一个锚点或者另一个物体的连接,可以是弹性的,也可以是非弹性的连接。直接上代码:

UIAttachmentBehavior *attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem: square offsetFromCenter: UIOffsetMake(0, - 40) attachedToAnchor: anchor];
attachmentBehavior.length = 100;
attachmentBehavior.damping = 0.3;
[myAnimator addBehavior: attachmentBehavior];

1.物体默认的锚点在中心,可以设置偏移。

2.步骤也是和其它得行为一样,设置参数,把该行为添加到myAnimator上。

3.更多的方法和属性,请自行参考苹果官方文档。

UISnapBehavior

吸附行为,将UIView通过动画吸附到某个点上。API非常简单,看下面代码就懂了。

UISnapBehavior *snapBehavior = [[UISnapBehavior alloc] initWithItem: ballView snapToPoint: centerBall.center];
snapBehavior.damping = 0.4;
[myAnimator addBehavior: snapBehavior];

UIPushBehavior

推动力,可以理解为向一个物体施加一个作用力,可以是持续的,也可以是瞬间的冲击。

UIPushBehavior *pushBehavior = [[UIPushBehavior alloc] initWithItems: @[square] mode: UIPushBehaviorModeInstantaneous];
pushBehavior.pushDirection = CGVectorMake(velocity.x / 1000, velocity.y / 1000);
[myAnimator addBehavior: pushBehavior];

UIDynamicItemBehavior

这其实不是一种行为,我的理解是对于将要进行各种行为的物体一些参数上面的设置,比如,弹力,震荡频率,密度等等。

UIDynamicItemBehavior *behavior3 = [[UIDynamicItemBehavior alloc] initWithItems: @[ballsArray2[2]]];
behavior3.elasticity = 0.5;
behavior3.friction = 0.3;
behavior3.resistance = 0.3;
[myAnimator addBehavior: behavior3];

3.组合(Group)

所有的行为都可以组合起来,如碰撞和重力,可以类似于物体做自由落体运动,然后和地面碰撞。代码如下:

myAnimator = [[UIDynamicAnimator alloc] initWithReferenceView: self];
//重力行为
UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems: @[ball]];
[myAnimator addBehavior: gravity];

//碰撞行为
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems: @[ball]];
collision.translatesReferenceBoundsIntoBoundary = YES;
collision.collisionDelegate = self;
[myAnimator addBehavior: collision];

//设置物体的一些相关的参数
UIDynamicItemBehavior *behavior = [[UIDynamicItemBehavior alloc] init];
behavior.elasticity = 0.8;
behavior.friction = 0.2;
behavior.resistance = 0.3;
behavior.density = 0.5;
behavior.angularResistance = 0.2;
[behavior addItem: ball];
[myAnimator addBehavior: behavior];

4.自定义行为(DIY)

1.将官方的行为打包

  • 继承UIDynamicBehavior(一个抽象类)
  • 实现添加组合行为的方法,最好和官方的保持一致,比如:initWithItems:,在里面调用addChildBehavior:方法添加需要组合的行为
  • 初始化该继承类,然后使用
@interface GravityWithCollisionBehavior : UIDynamicBehavior

- (instancetype)initWithItems: (NSArray *)items;

@end

@implementation GravityWithCollisionBehavior

- (instancetype)initWithItems: (NSArray *)items {
    self = [super init];
    if (self) {
        UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems: items];
        [self addChildBehavior: gravityBehavior];
        UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems: items];
        collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
        [self addChildBehavior: collisionBehavior];
    }
    return self;
}

@end

2.完全自定义行为

UIDynamicBehavior里提供了一个@property(nonatomic, copy) void (^action)(void),animator将会在行为发生期间,每一步都调用这个block。也就是说,你想自定义行为就得在这里写自己的一些代码。具体就是在这个block中向所有的item询问它们当前的center和transform状态,然后经过计算,把新的值赋予相应的item,从而该改变它们在屏幕上的位置,大小,角度,方向等等。

5.终结(Summary)

总的来说,iOS7引进的这套动力系统,大大丰富了我们动画表达,但是,该系统有着一些限制,会消耗一定的CPU资源,并且,当它们被添加到动画系统后,只能通过动画系统改变位置,而外部对于UIDynamicsItem的center,transform等设定是被忽略的,除此之外,该系统也没有现实世界那么精确,当计算迭代无法得到有效解的时候,动画将无法得到正确的呈现,所以,不要将动力系统神化。

6.Demo展示

UIDynamicAnimator
UIDynamicAnimator

源码下载

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容