iOS动画——DynamicAnimate
力学动画
以dynamicAnimate为首的力学动画是苹果在iOS7加入的API,里面包含了很多力学行为,这套API是基于Box2d实现的。其中包含了重力、碰撞、推、甩、和自定义行为。
涉及到的类如下
| 涉及类 | 描述 |
| UIDynamicAnimator | 相当于一个manager,用于管理所有添加的力学行为 |
| UIDynamicBehavior | 所有力学行为的父类,是一个抽象类 |
| UIGravityBehavior | 重力 |
| UICollisionBehavior | 碰撞,弹力 |
| UIAttachmentBehavior | 吸附力 |
| UIPushBehavior | 推力 |
| UISnapBehavior | 甩行力 |
| UIDynamicItemBehavior | 自定义行为 |
UIDynamicAnimator需要是一个实例变量,如果是局部变量动画会不起作用,个人感觉像是动作没有添加到RunLoop在函数执行结束后被释放了。
UIDynamicAnimator的初始化需要绑定一个视图,而且与视图必须是一对一的关系。
每一个行为都可以作用在很多的item上面,只要这个对象实现了<UIDynamicItem>协议,UIView默认就是所以不需要我们手动实现。
下面我们看几个例子来逐个解释
重力
重力很简单,我们先看一个demo
- (void)viewDidLoad {
[super viewDidLoad];
view = [[UIView alloc] initWithFrame:CGRectMake(, , , )];
view.backgroundColor = [UIColor grayColor];
[self.view addSubview:view];
_animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[view]];
[gravity setAngle:3.14/ magnitude:0.5];
[_animator addBehavior:gravity];
}
其中_animator是一个实例变量,上面解释过了。运行后会发现view像是在重力作用下向下做匀加速直线运动。
上面代码我们让重力作于在view上面,同时设置了重力的方向和大小。
@property (readwrite, nonatomic) CGVector gravityDirection;
@property (readwrite, nonatomic) CGFloat angle;
@property (readwrite, nonatomic) CGFloat magnitude;
- (void)setAngle:(CGFloat)angle magnitude:(CGFloat)magnitude;
上面是重力的方法和属性,我们逐个看一下。
gravityDirection是重力向量,既然是向量就有方向和大小。使用的坐标系为UIKit坐标系,所以默认左上角为(0,0)点,而向量的大小就是重力的大小。
angle为向量的方向,我们可以不通过gravityDirection来设定重力方向而用angle设置方向,因为angle更加的直观不用计算。
同理用magnitude来设置重力的大小。
弹力
弹力是一个很有意思的行为,除了我们设置弹力的item外,还要设置弹力的边界。
我们先看例子
UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[view]];
[collisionBehavior addBoundaryWithIdentifier:@"123ß" fromPoint:CGPointMake(, ) toPoint:CGPointMake(, )];
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
[_animator addBehavior:collisionBehavior];
弹力中有一个属性
@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;
是否把关联视图设置为边界,这里的关联视图指的就是UIDynamicAnimator中的视图。把该属性设置为YES,运行代码,大家会发view掉落到底部时会与底部放生弹性碰撞。
其实弹力行为提供了很多关于边界的方法
- (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;
- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier forPath:(UIBezierPath*)bezierPath;
- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2;
- (UIBezierPath*)boundaryWithIdentifier:(id <NSCopying>)identifier;
- (void)removeBoundaryWithIdentifier:(id <NSCopying>)identifier;
这些都比较简单就不一一解释了,感兴趣大家可以自己试一下。
下面着重介绍一个属性
@property (nonatomic, assign, readwrite) id <UICollisionBehaviorDelegate> collisionDelegate;
弹力有一个代理,是不是觉得很有意思,我们继续看例子
- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 atPoint:(CGPoint)p
{
NSLog(@"began contact item");
} - (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2
{
NSLog(@"end contanct item");
} - (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier atPoint:(CGPoint)p
{
NSLog(@"began contact boundary");
} - (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier
{
NSLog(@"end contact boundary");
}
我们实现弹力的代理并实现方法,运行程序,当初碰到底部的时候我们发现系统打印出了
-- ::49.123 TransAnimate[:] began contact boundary
-- ::49.157 TransAnimate[:] end contact boundary
-- ::49.524 TransAnimate[:] began contact boundary
-- ::49.557 TransAnimate[:] end contact boundary
每次发生弹力将要作用和结束作用都会分别调用代理方法。
根据方法名就可以明白,这两组代理方法一组针对物体碰撞,一组针对边界碰撞。
吸附力
关于吸附力,首先要解释一下,大家可以把吸附力理解为在吸附原点有一根棍,注意是棍不是绳子,连接着item。也就是说吸附力是刚性的。
下面看demo
UIAttachmentBehavior *attachment = [[UIAttachmentBehavior alloc] initWithItem:view attachedToAnchor:CGPointMake(, )];
attachment.length = ;
[_animator addBehavior:attachment];
可以看到这里我们用的吸附力的构造方法是一个点,length就代表"棍"的长度,运行程序发现物体在重力的作用下会以Anchor为中心,以length为半径,稍微转一下。
吸附力提供了很多的构造方法
- (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point;
- (instancetype)initWithItem:(id <UIDynamicItem>)item offsetFromCenter:(UIOffset)offset attachedToAnchor:(CGPoint)point; - (instancetype)initWithItem:(id <UIDynamicItem>)item1 attachedToItem:(id <UIDynamicItem>)item2;
- (instancetype)initWithItem:(id <UIDynamicItem>)item1 offsetFromCenter:(UIOffset)offset1 attachedToItem:(id <UIDynamicItem>)item2 offsetFromCenter:(UIOffset)offset2;
这两组构造方法的区别在于吸附对象,第一组是以点为对象,第二组以item为对象。
再解释一下offset,这里指的是被吸附对象的锚点偏移量,默认是center。
下面看一下属性
@property (readonly, nonatomic) UIAttachmentBehaviorType attachedBehaviorType; @property (readwrite, nonatomic) CGPoint anchorPoint; @property (readwrite, nonatomic) CGFloat length;
@property (readwrite, nonatomic) CGFloat damping;
@property (readwrite, nonatomic) CGFloat frequency;
UIAttachmentBehaviorType属性表明是吸附点是对象还是锚点。
下面几个分别是锚点,吸附长度,阻力和振动频率,就不说了。
推力
和重力差不多这里就不举例子了看一下属性和方法
- (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item; @property (nonatomic, readonly) UIPushBehaviorMode mode;
@property (nonatomic, readwrite) BOOL active; @property (readwrite, nonatomic) CGFloat angle; @property (readwrite, nonatomic) CGFloat magnitude;
@property (readwrite, nonatomic) CGVector pushDirection; - (void)setAngle:(CGFloat)angle magnitude:(CGFloat)magnitude;
下面的angle、magnitude、pushDirection和重力一模一样不多说了。
重点说一下UIPushBehaviorMode和active
UIPushBehaviorMode表示该推力是持续作用还是短暂作用,active表示推力是否还在作用。
上面的- (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;方法是说推力作用点的偏移量,默认是center。
甩行力
甩行力我也解释不是很清楚,我觉的可以理解为一个黑洞在吸附物体吧,这样应该挺形象的...
直接看例子吧
我们用故事板对控制器添加一个tapGesture的事件
- (IBAction)handleGesture:(UIGestureRecognizer *)sender {
CGPoint point = [sender locationInView:self.view];
UISnapBehavior *snap = [[UISnapBehavior alloc] initWithItem:view snapToPoint:point];
[_animator addBehavior:snap];
}
运行程序发现我们点击的位置,view会直接飞过去并且中间会有阻力。
甩行力只有一个属性,就是阻力。
自定义行为
一般我们都是用不上自定义行为的,只有在少数时候需要自己定制
我们可以定制的属性有很多
| 属性 | 描述 |
| desnsity | 密度,如果一个100*100点的物体,它的密度为1.0,作用力是1.0那么它的加速度就是100点/S2 |
| elasticity | 弹力洗漱,取值范围0.0~1.0,0.0代表没有弹力,1.0代表返券弹性碰撞 |
| friction | 摩擦系数,0.0表示没有摩擦力,1.0表示摩擦力很强,如果要设置更强的可以大于1 |
| resistance | 阻力,物体运动的时候,在线性方向的阻力,0.0没有阻力,CGFLOAT_MAX表示最大阻力 |
| allowRotation | 是否允许旋转。 |
| angularResistance | 角阻力,物体旋转时候,旋转方向的阻力 |
iOS动画——DynamicAnimate的更多相关文章
- (转)iOS动画Core Animation
文章转载:http://blog.sina.com.cn/s/blog_7b9d64af0101b8nh.html 在iOS中动画实现技术主要是:Core Animation. Core Animat ...
- 解析 iOS 动画原理与实现
这篇文章不会教大家如何实现一个具体的动画效果,我会从动画的本质出发,来说说 iOS 动画的原理与实现方式. 什么是动画 动画,顾名思义,就是能“动”的画.人的眼睛对图像有短暂的记忆效应,所以当眼睛看到 ...
- IOS动画隐式,显式,翻页
// ViewController.m // IOS动画0817 // // Created by 张艳锋 on 15/8/17. // Copyright (c) 2015年 张艳锋. Al ...
- iOS动画原理
1. iOS动画原理 本质:动画对象(这里是UIView)的状态,基于时间变化的反应 分类:可以分为显式动画(关键帧动画和逐帧动画)和隐式动画 关键帧和逐帧总结:关键帧动画的实现方式,只需要修改某个属 ...
- iOS 动画基础
原文:http://www.cnblogs.com/lujianwenance/p/5733846.html 今天说一下有关动画的基础,希望能帮助到一些刚接触iOS动画或者刚开始学习iOS的同学, ...
- ios 动画效果CATransition笔记
初学ios开发,很多概念还不清楚,所以只有边学边做例子.又怕学了后面忘了前面,因此用自己的博客来纪录自己的学习历程,也是对自己学习不要懈怠做个监督. 刚学ios做动画效果.因为ios封装得很好,实现i ...
- IOS动画总结
IOS动画总结 一.基本方式:使用UIView类的UIViewAnimation扩展 + (void)beginAnimations:(NSString *)animationID context ...
- ios 动画学习的套路 (二)
有它们俩你就够了! 说明:下面有些概念我说的不怎么详细,网上实在是太多了,说了我觉得也意义不大了!但链接都给大家了,可以自己去看,重点梳理学习写动画的一个过程和一些好的博客! (一) 说说这两个三方库 ...
- iOS动画学习-视觉效果
CALayer不仅仅是iOS动画学习-CALayer中介绍的那些内容,他还有一些其他属性,比如shadowColor,borderWidth,borderColor等等,这些属性我们只需要简单点设置就 ...
随机推荐
- vue axios请求超时,设置重新请求的完美解决方法
//在main.js设置全局的请求次数,请求的间隙 axios.defaults.retry = 4; axios.defaults.retryDelay = 1000; axios.intercep ...
- 通过注解配置Bean(2)
问:怎么用注解来配置bean与bean之间的引用关系? [组件装配] 1.<context:component-scan> 元素还会自动注册AutowiredAnnotationBeanP ...
- 【Codeforces 404C】Restore Graph
[链接] 我是链接,点我呀:) [题意] 每个节点的度数不超过k 让你重构一个图 使得这个图满足 从某个点开始到其他点的最短路满足输入的要求 [题解] 把点按照dep的值分类 显然只能由dep到dep ...
- JavaSE 学习笔记之反射技术(二十四)
反射技术:其实就是动态加载一个指定的类,并获取该类中的所有的内容.而且将字节码文件封装成对象,并将字节码文件中的内容都封装成对象,这样便于操作这些成员.简单说:反射技术可以对一个类进行解剖. 反射的好 ...
- noip模拟赛 whzzt-Conscience
分析:数据中并不存在无解的情况...... 每个摄像头都要覆盖尽可能多的点,按照y从小到大排序.对于每一列,只用判断第一个没有被观测到的就可以了,这个点必须要放摄像头,因为除了它自己没有其它的摄像头能 ...
- Mybatis错误——Could not find parameter map java.util.Map
错误信息 org.apache.ibatis.builder.IncompleteElementException: Could not find parameter map java.util.Ma ...
- 用xtrabackup+binlog恢复误删除的数据库
关键技术,数据库产生的二进制文件,在主库就是binlog在从库就是relay-log,用最新的物理备份可以新启动个新实例,可以模拟个从库,把主库的binlog复制到新的数据库实例上,利用主从复制和物理 ...
- - > 动规讲解基础讲解八——正整数分组
将一堆正整数分为2组,要求2组的和相差最小.例如:1 2 3 4 5,将1 2 4分为1组,3 5分为1组,两组和相差1,是所有方案中相差最少的. 整数个数n<=100,所有整数的和<=1 ...
- windows 2008 64位在指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配
在本机32位环境中使用access数据库正常. 公布到server上时提示:在指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配 server是64位环境.windows 2008,64位的t ...
- Cannot update identity column 'XXX'
Sqlserver -- 怎样改动设置主键的id能够手动更新? #1 打开表的设计界面 #2 将主键id的is Identity的属性改成No 这样就能够通过Update语句来更新表的主键id了. 怎 ...