UIKit動力學最大的特點是將現(xiàn)實世界動力驅(qū)動的動畫引入了UIKit览徒,比如重力突诬,鉸鏈連接扯键,碰撞睦袖,懸掛等效果珊肃,即將2D物理引擎引入了UIKit
注意:UIKit動力學的引入荣刑,并不是為了替代CA或者UIView動畫,在絕大多數(shù)情況下CA或者UIView動畫仍然是最優(yōu)方案伦乔,只有在需要引入逼真的交互設(shè)計的時候厉亏,才需要使用UIKit動力學它是作為現(xiàn)有交互設(shè)計和實現(xiàn)的一種補充
?其他2D仿真引擎:
BOX2D:C語言框架,免費
Chipmunk:C語言框架免費烈和,其他版本收費
UIDynamic中的三個重要概念
?Dynamic
Animator:動畫者爱只,為動力學元素提供物理學相關(guān)的能力及動畫,同時為這些元素提供相關(guān)的上下文招刹,是動力學元素與底層iOS物理引擎之間的中介恬试,將Behavior對象添加到Animator即可實現(xiàn)動力仿真
?DynamicAnimatorItem:動力學元素,是任何遵守了UIDynamicItem協(xié)議的對象疯暑,從iOS7.0開始训柴,UIView和UICollectionViewLayoutAttributes默認實現(xiàn)該協(xié)議。如果自定義的對象實現(xiàn)了該協(xié)議妇拯,即可通過DynamicAnimator實現(xiàn)物理仿真
?UIDynamicBehavior:仿真行為幻馁,是動力學行為的父類洗鸵,基本的動力學行為類UIGravityBehavior、UICollisionBehavior仗嗦、UIAttachmentBehavior膘滨、UISnapBehavior、UIPushBehavior以及UIDynamicItemBehavior均繼承自該父類
動力學動畫元素(Dynamic
Animator Item)協(xié)議
?只有遵守了UIDynamicItem協(xié)議的對象才可以參與到UI動力學仿真中
?從iOS
7開始稀拐,UIView和UICollectionViewLayoutAttributes類默認實現(xiàn)了該協(xié)議
?協(xié)議定義的屬性:
bounds:Dynamic
animator需要動畫元素的邊框時調(diào)用火邓,只讀屬性,用于計算物體的邊界以及質(zhì)量
center:動力學元素的中心點钩蚊,讀寫屬性
transform:動力學元素的旋轉(zhuǎn)角度贡翘,讀寫屬性(需要指定Layer的形變屬性)
動力學行為(Dynamic
Behavior)
一個動力學行為可以為一個或者多個動力學元素賦予參與在二維動畫中所具備的行為
?iOS7.0中提供的動力學行為包括:
UIGravityBehavior:重力行為
UICollisionBehavior:碰撞行為
UIAttachmentBehavior:附著行為
UISnapBehavior:吸附行為
UIPushBehavior:推行為
UIDynamicItemBehavior:動力學元素行為
?所有的UIDynamicBehavior都是可以獨立作用,同時也遵守力的合成砰逻。也就是說鸣驱,組合使用行為可以實現(xiàn)一些較復雜的效果
重力行為(Gravity)
?重力行為用于給動力學元素指定一個重力向量
//實例化一個重力行為,并傳入需要做動力仿真的對象view
UIGravityBehavior*gravity = [[UIGravityBehavioralloc]initWithItems:@[view]];
//將重力行為添加到animator
[animatoraddBehavior:gravity];
碰撞行為(Collision)
?碰撞行為用于指定一組動力學元素蝠咆,在指定的邊界范圍內(nèi)踊东,可以彼此發(fā)生碰撞
?碰撞行為提供了代理方法,可用于在物體碰撞前刚操、后對動力學元素做碰撞后續(xù)的處理
//實例化碰撞行為闸翅,并指定view參與碰撞
UICollisionBehavior*collsion= [[UICollisionBehavioralloc]initWithItems:@[view]];
//指定是否啟用參照系的邊界
collsion.translatesReferenceBoundsIntoBoundary=YES;
//將碰撞行為添加至animator
吸附行為(Snap)
?吸附行為可以將視圖通過動畫吸附到某個點上
?初始化設(shè)定一下UISnapBehavior的initWithItem:snapToPoint:即可
?屬性:
·damping:振幅大小,默認為0.5f
附著行為(Attachment)
?附著行為描述一個視圖與一個錨點或者另一個視圖相連接的情況
?附著行為描述的是兩點之間的連接情況菊霜,可以模擬剛性或者彈性連接
?在多個物體間設(shè)定多個UIAttachmentBehavior坚冀,可以模擬多物體連接
·
?屬性:
·attachedBehaviorType:連接類型(連接到錨點或視圖)
·items:連接視圖數(shù)組
·anchorPoint:連接錨點
·length:距離連接錨點的距離
?只要設(shè)置了以下兩個屬性,即為彈性連接
·damping:振幅大小
·frequency:振動頻率
推行為(Push)
?推行為可以為一個視圖施加一個作用力鉴逞,該力可以是持續(xù)的记某,也可以是一次性的
?可以設(shè)置力的大小,方向和作用點等信息
·
?屬性:
?mode:推動類型(一次性或是持續(xù)推)
?active:是否激活构捡,如果是一次性推液南,需要激活
?angle:推動角度
?magnitude:推動力量
動力學元素行為(DynamicItem)
?是一個輔助的行為,用來設(shè)置運動學元素參與物理仿真過程中的參數(shù)勾徽,如:彈性系數(shù)滑凉、摩擦系數(shù)、密度喘帚、阻力畅姊、角阻力以及是否允許旋轉(zhuǎn)等
·
·elasticity(彈性系數(shù)):決定了碰撞的彈性程度,比如碰撞時物體的彈性
·friction(摩擦系數(shù)):決定了沿接觸面滑動時的摩擦力大小
·density(密度):跟size結(jié)合使用吹由,計算物體的總質(zhì)量若未。質(zhì)量越大,物體加速或減速就越困難
·resistance(阻力):決定線性移動的阻力大小溉知,與摩擦系數(shù)不同陨瘩,摩擦系數(shù)只作用于滑動運動
·angularResistance(角阻力):決定旋轉(zhuǎn)運動時的阻力大小
·allowsRotation(允許旋轉(zhuǎn)):這個屬性很有意思腕够,它在真實的物理世界沒有對應(yīng)的模型。設(shè)置這個屬性為NO物體就完全不會轉(zhuǎn)動舌劳,而無論施加多大的轉(zhuǎn)動力
設(shè)置不可見碰撞邊界并跟蹤碰撞情況
// 5.1設(shè)置障礙物碰撞邊界
CGPointtoPoint =CGPointMake(barrier.frame.origin.x+ barrier.frame.size.width,
barrier.frame.origin.y+ barrier.frame.size.height);
[collisionaddBoundaryWithIdentifier:@"barrier"fromPoint:barrier.frame.origintoPoint:toPoint];
// 6.設(shè)置物體的彈性系數(shù)
UIDynamicItemBehavior *item =
[[UIDynamicItemBehavior alloc] initWithItems:@[view]];
[item
setElasticity:0.5f];
// 7.監(jiān)聽碰撞動作
collision.action =
^{
NSLog(@"%@", NSStringFromCGRect(view.frame));
};
在碰撞通知代理方法中修改視圖顏色
UIView*view = (UIView*)item;
//動畫改變碰撞物體的顏色
NSString*ID = [NSStringstringWithFormat:@"%@", identifier];
if([IDisEqualToString:@"barrier"]) {
view.backgroundColor= [UIColorgreenColor];
[UIViewanimateWithDuration:0.3fanimations:^{
view.backgroundColor= [UIColorblueColor];
}];
}
吸附行為
//刪除之前的吸附行為
[_animatorremoveBehavior:_snap];
CGPointlocation = [senderlocationInView:self.view];
_snap= [[UISnapBehavioralloc]initWithItem:_boxImageViewsnapToPoint:location];
//生成隨機振幅
CGFloatdamping =arc4random_uniform(10) +1;
_snap.damping= damping /10.0f;
[_animatoraddBehavior:_snap];
附加剛性行為
if(UIGestureRecognizerStateBegan== sender.state) {
//創(chuàng)建附加剛性行為
CGPointanchorPoint =CGPointMake(_boxImageView.center.x,_boxImageView.center.y);
_attachment= [[UIAttachmentBehavioralloc]initWithItem:_boxImageViewoffsetFromCenter:UIOffsetMake(-25.0, -25.0)attachedToAnchor:anchorPoint];
[_animatoraddBehavior:_attachment];
}elseif(UIGestureRecognizerStateChanged== sender.state) {
//設(shè)置行為的錨點
[_attachmentsetAnchorPoint:[senderlocationInView:self.view]];
}elseif(UIGestureRecognizerStateEnded== sender.state) {
//刪除附加行為
[_animatorremoveBehavior:_attachment];
}
注:偏移點偏移一定位置帚湘,可以使得在拖動手指時產(chǎn)生旋轉(zhuǎn)的效果
附加彈性行為
if(UIGestureRecognizerStateBegan== sender.state) {
CGPointanchor =CGPointMake(_boxImageView.center.x,_boxImageView.center.y-100);
_attachment= [[UIAttachmentBehavioralloc]initWithItem:_boxImageViewattachedToAnchor:anchor];
[_animatoraddBehavior:_attachment];
[_attachmentsetFrequency:1.0f];
[_attachmentsetDamping:0.1f];
}elseif(UIGestureRecognizerStateChanged== sender.state) {
[_attachmentsetAnchorPoint:[senderlocationInView:self.view]];
}elseif(UIGestureRecognizerStateEnded== sender.state) {
[_animatorremoveBehavior:_attachment];
}
注:設(shè)置了frequency和damping屬性,創(chuàng)建的即為彈性連接
施加一個力
//計算兩點之間距離
CGFloatdistance =sqrtf(powf(p.x-_firstPoint.x,2.0) +powf(p.y-_firstPoint.y,2.0));
CGFloatangle =atan2(p.y-_firstPoint.y, p.x-_firstPoint.x);
_push.magnitude= distance /20;
_push.angle= angle;
[_pushsetActive:YES];