UIDynamicAnimator :为我们提供了一些基于物理学的动画,让我们更容易的做出一些与现实世界(物理行为)相符的逼真的二维动画。
iOS 7 之后,Apple 给我们提供了一个与物理学相关(physics-related)的 API,与之相关的有两个类和一个协议:
-
UIDynamicAnimator
- 动画生成器,我们只需配置好属性并提交给它,其余的由它去做。 -
UIDynamicBehavior
- 一些物理学行为。它的子类提供了一些具体的物理学行为。 -
UIDynamicItem
- 这是一个协议,只要遵循了这个协议的任何对象, 都可以成为UIDynamicAnimator
动画的对象。UICollectionViewLayoutAttributes
,UIDynamicItemGroup(iOS 9.0 +)
,UIView
都遵循了这个协议。
一张图更好的理解:
UIDynamicAnimator
它像一个驱动类
,它关联了遵守UIDynamicItem
协议的可动画对象Item
和行为Behavior
,给动画的执行提供了上下文,之后动画的执行由它驱动。它有类似于集合
的一些方法:- addBehavior:
,- removeBehavior:
,- removeAllBehaviors
.
其中,需要注意的有几点:
- 初始化方法:
- initWithReferenceView:
中传入的是参考view
,而不是直接动画的view
。 - 动画执行完毕后,可动画对象的一些属性会被改变而不会复原(frame、color、size and so on...)。所以,如果我们需要重复执行一个动画的话,我们需要在合适的时机重新设置这些值。
APIs
UIDynamicAnimator
的API
只有几个,如下:
UIDynamicBehavior
提供动画行为的类。使用中我们更多的是直接使用他的子类。子类具体如图1所示。它的子类实现了各种物理学行为。具体可以查看每个子类的头文件。他们有几个通用的属性:
UIAttachmentBehavior
Discussion
UIAttachmentBehavior
可以把两个view
或者view
和 anchorPoint
关联起来。
APIs
它有一些自己的属性,其中比较重要的是:
-
damping
: 阻尼,要和阻力做区分,当此值设置为1
时,达到临界阻尼,到达临界阻尼后我们的动画便不再会有回弹的效果。 -
frequency
: 频率,行为的频率,单位Hz
,值越大,频率越高,动画过程越快,动画效果越不明显。 -
length
: 关联的两个对象(view
和view
或者view
和anchorPoint
) 动画结束后两者锚点(anchor
)之间的距离长度。 -
frictionTorque
: 摩擦力矩,作用暂时不详。
demo
基于苹果爸爸强大的封装,我们可以很容易的实现下面的效果:
完整的代码为:
UIAttachmentBehavior *attachment = [[UIAttachmentBehavior alloc] initWithItem:self.animationView attachedToItem:self.relyView];
attachment.damping = 0.5;
attachment.frequency = 1.f;
attachment.length = 80;
// attachment.frictionTorque = 1.f;
attachment.action = ^{
NSLog(@"%@",NSStringFromCGRect(self.animationView.frame));
};
[self.animator addBehavior:attachment];
你可以自己调整下参数,看看之后的效果。
UIGravityBehavior
Discussion
UIGravityBehavior
模拟的是现实生活中的重力特性。
APIs
能让我们自定义的API
只有几个,其中:
-
gravityDirection
: 重力方向。单位向量,默认是(0.0,1.0),即重力向下。重力坐标系和UIKit
的一样。y
轴向下为正,x
轴向左为正。如下:
UICollisionBehavior
Discussion
UICollisionBehavior
模拟的是现实生活中的碰撞特性。在碰撞中,我们需要指定碰撞的边界,碰撞的边界可以是另一个view
,可以是一个边界。如果我们没有指定边界的话, 并且也没有将参考视图作为边界,那么碰撞行为就不会发生。
APIs
-
collisionMode
: 指定碰撞的边界类型。 -
translatesReferenceBoundsIntoBoundary
: 把参考视图转化为碰撞的边界。 -
- addBoundaryWithIdentifier:forPath:
:指定一个贝塞尔路径作为碰撞边界,并给这个碰撞边界一个标记。 -
- addBoundaryWithIdentifier:fromPoint:toPoint
:指定两个点之间的连线为碰撞边界。如果指定collisionMode
为UICollisionBehaviorModeItems
,则设置这个属性无效。
UIPushBehavior
Discussion
UIPushBehavior
可以对一个物体施加一个连续的
或者瞬时
的力,并改变物体的位置。
APIs
-
UIPushBehaviorMode
:推力的类型,枚举值。分为持续(UIPushBehaviorModeContinuous
)和瞬时(UIPushBehaviorModeInstantaneous
)。 -
angle
: 推力的角度。 -
magnitude
: 推力的大小。 -
pushDirection
: 推力的方向,和UIKit
的坐标系相同。 -
active
: 推力当前的状态,分为active
和inactive
.
SnapViewController
Discussion
UISnapBehavior
模拟的是物体吸附的行为,并且伴有弹簧动画。
APIs
-
damping
: 阻尼。 -
snapPoint
: 和anchorPoint
的作用类似,代表的是当前Item
的锚点位置。
UIDynamicItemBehavior
如果你不满足于上面的属性,那么UIDynamicItemBehavior
给你提供了更多的选择。我们可以使用UIDynamicItemBehavior
,来设置Item
的更多属性。包括:
elasticity
: 弹力。在0
~1
之间,0
代表无弹性,1
代表弹性碰撞friction
: 摩擦力。charge
: 电荷。决定了物体和电场或者磁场之间的相互作用力。density
: 密度。决定了动力项的其他属性的表现,比如摩擦、碰撞等。angularResistance
: 角度阻力。有效范围在0
~CGFlOAT_MAX
,值越大,在动力行为中物体越不容易旋转。resistance
: 阻力。动力项的线性阻力。有效值范围为0.0
~CGFLOAT_MAX
。anchored
: 是否固定锚点。如果这个值为YES
,那么,当发生碰撞的时候,物体不会移动,但参与碰撞。效果类似于一个碰撞边界。- addLinearVelocity:forItem:
: 给物体增加一个线性速度。- addAngularVelocity:forItem:
: 给物体增加一个角速度。allowsRotation
: 值为NO
时,强制物体再发生碰撞之后不会旋转。
小结
这是 Apple 在 iOS 7
推出的功能,在iOS 9
之后增加了一些新的API
。算是一个老功能,现在才研究起来算是补作业了。基本都是根据官方文档摸索着写的一个小Demo,实现了一些基本的小效果。更加炫酷的就需要靠强大的 idea 了。