UIDynamic——UIKit動(dòng)力學(xué)

UIKit動(dòng)力學(xué)最大的特點(diǎn)是將現(xiàn)實(shí)世界動(dòng)力驅(qū)動(dòng)的動(dòng)畫引入了UIKit,比如重力,鉸鏈連接,碰撞,懸掛等效果,即將2D物理引擎引入了UIKit

注意:UIKit動(dòng)力學(xué)的引入,并不是為了替代CA或者UIView動(dòng)畫,在絕大多數(shù)情況下CA或者UIView動(dòng)畫仍然是最優(yōu)方案,只有在需要引入逼真的交互設(shè)計(jì)的時(shí)候,才需要使用UIKit動(dòng)力學(xué)它是作為現(xiàn)有交互設(shè)計(jì)和實(shí)現(xiàn)的一種補(bǔ)充

?其他2D仿真引擎:

BOX2D:C語言框架,免費(fèi)

Chipmunk:C語言框架免費(fèi),其他版本收費(fèi)

UIDynamic中的三個(gè)重要概念

?Dynamic

Animator:動(dòng)畫者,為動(dòng)力學(xué)元素提供物理學(xué)相關(guān)的能力及動(dòng)畫,同時(shí)為這些元素提供相關(guān)的上下文,是動(dòng)力學(xué)元素與底層iOS物理引擎之間的中介,將Behavior對(duì)象添加到Animator即可實(shí)現(xiàn)動(dòng)力仿真

?DynamicAnimatorItem:動(dòng)力學(xué)元素,是任何遵守了UIDynamicItem協(xié)議的對(duì)象,從iOS7.0開始,UIView和UICollectionViewLayoutAttributes默認(rèn)實(shí)現(xiàn)該協(xié)議。如果自定義的對(duì)象實(shí)現(xiàn)了該協(xié)議,即可通過DynamicAnimator實(shí)現(xiàn)物理仿真

?UIDynamicBehavior:仿真行為,是動(dòng)力學(xué)行為的父類,基本的動(dòng)力學(xué)行為類UIGravityBehavior、UICollisionBehavior、UIAttachmentBehavior、UISnapBehavior、UIPushBehavior以及UIDynamicItemBehavior均繼承自該父類

動(dòng)力學(xué)動(dòng)畫元素(Dynamic

Animator Item)協(xié)議

?只有遵守了UIDynamicItem協(xié)議的對(duì)象才可以參與到UI動(dòng)力學(xué)仿真中

?從iOS

7開始,UIView和UICollectionViewLayoutAttributes類默認(rèn)實(shí)現(xiàn)了該協(xié)議

?協(xié)議定義的屬性:

bounds:Dynamic

animator需要?jiǎng)赢嬙氐倪吙驎r(shí)調(diào)用,只讀屬性,用于計(jì)算物體的邊界以及質(zhì)量

center:動(dòng)力學(xué)元素的中心點(diǎn),讀寫屬性

transform:動(dòng)力學(xué)元素的旋轉(zhuǎn)角度,讀寫屬性(需要指定Layer的形變屬性)

動(dòng)力學(xué)行為(Dynamic

Behavior)

一個(gè)動(dòng)力學(xué)行為可以為一個(gè)或者多個(gè)動(dòng)力學(xué)元素賦予參與在二維動(dòng)畫中所具備的行為

?iOS7.0中提供的動(dòng)力學(xué)行為包括:

UIGravityBehavior:重力行為

UICollisionBehavior:碰撞行為

UIAttachmentBehavior:附著行為

UISnapBehavior:吸附行為

UIPushBehavior:推行為

UIDynamicItemBehavior:動(dòng)力學(xué)元素行為

?所有的UIDynamicBehavior都是可以獨(dú)立作用,同時(shí)也遵守力的合成。也就是說,組合使用行為可以實(shí)現(xiàn)一些較復(fù)雜的效果

重力行為(Gravity)

?重力行為用于給動(dòng)力學(xué)元素指定一個(gè)重力向量

//實(shí)例化一個(gè)重力行為,并傳入需要做動(dòng)力仿真的對(duì)象view

UIGravityBehavior*gravity = [[UIGravityBehavioralloc]initWithItems:@[view]];

//將重力行為添加到animator

[animatoraddBehavior:gravity];

碰撞行為(Collision)

?碰撞行為用于指定一組動(dòng)力學(xué)元素,在指定的邊界范圍內(nèi),可以彼此發(fā)生碰撞

?碰撞行為提供了代理方法,可用于在物體碰撞前、后對(duì)動(dòng)力學(xué)元素做碰撞后續(xù)的處理

//實(shí)例化碰撞行為,并指定view參與碰撞

UICollisionBehavior*collsion= [[UICollisionBehavioralloc]initWithItems:@[view]];

//指定是否啟用參照系的邊界

collsion.translatesReferenceBoundsIntoBoundary=YES;

//將碰撞行為添加至animator

吸附行為(Snap)

?吸附行為可以將視圖通過動(dòng)畫吸附到某個(gè)點(diǎn)上

?初始化設(shè)定一下UISnapBehavior的initWithItem:snapToPoint:即可

?屬性:

·damping:振幅大小,默認(rèn)為0.5f

附著行為(Attachment)

?附著行為描述一個(gè)視圖與一個(gè)錨點(diǎn)或者另一個(gè)視圖相連接的情況

?附著行為描述的是兩點(diǎn)之間的連接情況,可以模擬剛性或者彈性連接

?在多個(gè)物體間設(shè)定多個(gè)UIAttachmentBehavior,可以模擬多物體連接

·

?屬性:

·attachedBehaviorType:連接類型(連接到錨點(diǎn)或視圖)

·items:連接視圖數(shù)組

·anchorPoint:連接錨點(diǎn)

·length:距離連接錨點(diǎn)的距離

?只要設(shè)置了以下兩個(gè)屬性,即為彈性連接

·damping:振幅大小

·frequency:振動(dòng)頻率

推行為(Push)

?推行為可以為一個(gè)視圖施加一個(gè)作用力,該力可以是持續(xù)的,也可以是一次性的

?可以設(shè)置力的大小,方向和作用點(diǎn)等信息

·

?屬性:

?mode:推動(dòng)類型(一次性或是持續(xù)推)

?active:是否激活,如果是一次性推,需要激活

?angle:推動(dòng)角度

?magnitude:推動(dòng)力量

動(dòng)力學(xué)元素行為(DynamicItem)

?是一個(gè)輔助的行為,用來設(shè)置運(yùn)動(dòng)學(xué)元素參與物理仿真過程中的參數(shù),如:彈性系數(shù)、摩擦系數(shù)、密度、阻力、角阻力以及是否允許旋轉(zhuǎn)等

·

·elasticity(彈性系數(shù)):決定了碰撞的彈性程度,比如碰撞時(shí)物體的彈性

·friction(摩擦系數(shù)):決定了沿接觸面滑動(dòng)時(shí)的摩擦力大小

·density(密度):跟size結(jié)合使用,計(jì)算物體的總質(zhì)量。質(zhì)量越大,物體加速或減速就越困難

·resistance(阻力):決定線性移動(dòng)的阻力大小,與摩擦系數(shù)不同,摩擦系數(shù)只作用于滑動(dòng)運(yùn)動(dòng)

·angularResistance(角阻力):決定旋轉(zhuǎn)運(yùn)動(dòng)時(shí)的阻力大小

·allowsRotation(允許旋轉(zhuǎn)):這個(gè)屬性很有意思,它在真實(shí)的物理世界沒有對(duì)應(yīng)的模型。設(shè)置這個(gè)屬性為NO物體就完全不會(huì)轉(zhuǎn)動(dòng),而無論施加多大的轉(zhuǎn)動(dòng)力

設(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)聽碰撞動(dòng)作

collision.action =

^{

NSLog(@"%@", NSStringFromCGRect(view.frame));

};

在碰撞通知代理方法中修改視圖顏色

UIView*view = (UIView*)item;

//動(dòng)畫改變碰撞物體的顏色

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];

//生成隨機(jī)振幅

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è)置行為的錨點(diǎn)

[_attachmentsetAnchorPoint:[senderlocationInView:self.view]];

}elseif(UIGestureRecognizerStateEnded== sender.state) {

//刪除附加行為

[_animatorremoveBehavior:_attachment];

}

注:偏移點(diǎn)偏移一定位置,可以使得在拖動(dòng)手指時(shí)產(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)建的即為彈性連接

施加一個(gè)力

//計(jì)算兩點(diǎn)之間距離

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];

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容