在iOS7上新增加了UIKit Dynamic讨韭,它能夠讓UIView模擬逼真的物理效果脂信。如重力,碰撞透硝,彈簧狰闪,吸附等效果,有了這些效果能輕松的提高應(yīng)用的用戶體驗(yàn)濒生。想要實(shí)現(xiàn)這些力學(xué)動(dòng)畫(huà)效果埋泵,首先要?jiǎng)?chuàng)建一個(gè)力學(xué)動(dòng)畫(huà)生成器(UIDynamicAnimator),然后使用各種行為進(jìn)行定制罪治,可用于定制UIDynamicAnimator的行為的類有:UIAttachmentBehavior
丽声,UICollisionBehavior
,UIGravityBehavior
觉义,UIDynamicItemBehavior
恒序,UIPushBehavior
,UISnapBehavior
谁撼。他們能夠賦予UIView逼真的行為和動(dòng)畫(huà)歧胁。
NOTE:每個(gè)力學(xué)動(dòng)畫(huà)生成器都是獨(dú)立的滋饲,多個(gè)動(dòng)畫(huà)力學(xué)生成器可同時(shí)運(yùn)行。要讓力學(xué)動(dòng)畫(huà)生成器持續(xù)運(yùn)行喊巍,必須要有指向它的有效應(yīng)用屠缭。一旦動(dòng)畫(huà)處于靜止?fàn)顟B(tài)(如彈簧效果恢復(fù)原狀)之后,力學(xué)動(dòng)畫(huà)生成器將暫停崭参,不在執(zhí)行任何計(jì)算了呵曹。但是對(duì)于未用的力學(xué)動(dòng)畫(huà)生成器,最好把它刪除掉何暮。
生成一個(gè)力學(xué)動(dòng)畫(huà)生成器
UIDynamicAnimator *animator =[ [UIDynamicAnimator alloc] initWithReferenceView:self.view];//行為視圖的父視圖必須是動(dòng)畫(huà)生成器的參考視圖
[animator addBehavior:aDynamicBeahvior];//aDynamicBeahvior是一個(gè)行為
重力(UIGravityBehavior)
重力的效果如圖所示:
對(duì)于重力行為奄喂,需要注意的有角度(angle)和量級(jí)(magnitude,我也叫它重力加速度)海洼,實(shí)現(xiàn)代碼如下:
UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems:@[footballView]];
//angle:角度(弧度) magnitude:量級(jí)(重力系數(shù))
[gravityBehavior setAngle:3.14/2 magnitude:0.1f];
[self.animator addBehavior:gravityBehavior];
碰撞(UICollisionBehavior)
說(shuō)到碰撞跨新,一個(gè)是物體之間的碰撞,一個(gè)是與邊界的碰撞坏逢,在上面的重力效果演示圖中域帐,足球從上落下,一直落到屏幕之外是整,這是由于我們沒(méi)有給他設(shè)置邊界
肖揣。我們看看碰撞的效果圖:
我給圖中的籃球
和足球
設(shè)置了重力效果和碰撞效果,代碼如下:
UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems:@[self.footballView,self.basketballView]];
[gravityBehavior setAngle:3.14/2 magnitude:0.1f];
//碰撞效果
UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[self.footballView,self.basketballView]];
[collisionBehavior setCollisionMode:UICollisionBehaviorModeEverything];//碰撞效果浮入,必須指定的
/**
* UICollisionBehaviorModeEverything:物體既相互碰撞又與邊界碰撞
* UICollisionBehaviorModeBoundaries:物體不相互碰撞龙优,只與邊界碰撞
* UICollisionBehaviorModeItems:物體相互碰撞,不與邊界碰撞
*/
//設(shè)置邊界為動(dòng)畫(huà)器參考view的視圖范圍
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
//代理可以監(jiān)聽(tīng)碰撞
collisionBehavior.collisionDelegate = self;
[self.animator addBehavior:gravityBehavior];
[self.animator addBehavior:collisionBehavior];
連接(UIAttachmentBehavior)
連接就是讓一個(gè)物體的行為和移動(dòng)受另外一個(gè)物體的移動(dòng)事秀。使用連接效果要指定連接點(diǎn)彤断。效果大概如下:
在上面的效果演示圖中,我添加了一個(gè)pan
手勢(shì)秽晚,然后取pan
的坐標(biāo)點(diǎn)讓其成為籃球
的center
,在連接效果的作用下瓦糟,足球會(huì)由于籃球的移動(dòng)而動(dòng),具體代碼如下:
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[self.footballView,self.basketballView]];
[collisionBehavior setCollisionMode:UICollisionBehaviorModeEverything];
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
CGPoint basketballCenter = CGPointMake(self.basketballView.center.x, self.basketballView.center.y);
self.attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:self.basketballView attachedToAnchor:basketballCenter];
[self.animator addBehavior:collisionBehavior];
[self.animator addBehavior:self.attachmentBehavior];
self.panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handAttachmentesture:)];
[self.view addGestureRecognizer:self.panGesture];
- (void)handAttachmentesture:(UIPanGestureRecognizer *)gesture{
CGPoint gesturePoint = [gesture locationInView:self.view];
self.basketballView.center = gesturePoint;
[self.attachmentBehavior setAnchorPoint:gesturePoint];
}
彈簧
彈簧效果應(yīng)該都懂赴蝇,先看看效果:
彈簧效果其實(shí)是在連接效果上實(shí)現(xiàn)的菩浙,恰當(dāng)設(shè)置連接效果的Frequency
,Damping
這二個(gè)屬性后就可以達(dá)到彈簧的效果了,在上面的代碼加上:
[self.attachmentBehavior setFrequency:1.0f];//振動(dòng)頻率
[self.attachmentBehavior setDamping:0.1f];//熨平動(dòng)畫(huà)的峰值
吸附(UISnapBehavior)
吸附效果有點(diǎn)像磁鐵吸鐵塊一樣句伶,只要我們指定一個(gè)點(diǎn)劲蜻,具有吸附效果的物體
就有了被磁鐵
吸過(guò)去的效果了。
我們?cè)谄聊簧现付ㄒ粋€(gè)tap
手勢(shì)考余,講tap
后的點(diǎn)作為磁鐵
,代碼:
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
self.tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handTapGesture:)];
[self.view addGestureRecognizer:self.tapGesture];
- (void)handTapGesture:(UITapGestureRecognizer *)gesture{
CGPoint point = [gesture locationInView:self.view];
if (self.snapBehavior == nil) {
self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.footballView snapToPoint:point];
self.snapBehavior.damping = 0.75;
}
[self.animator addBehavior:self.snapBehavior];
}
推力
推力指得是可以對(duì)物體施加推力先嬉,效果:
我用了一個(gè)tap
手勢(shì)作為施加推力的源,代碼如下:
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
UICollisionBehavior * collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[self.footballView]];
[self.animator addBehavior:collisionBehavior];
UIPushBehavior *pushBehavior = [[UIPushBehavior alloc] initWithItems:@[self.footballView] mode:UIPushBehaviorModeInstantaneous];
pushBehavior.angle = 0.0;
pushBehavior.magnitude = 0.;
self.pushBehavior = pushBehavior;
[self.animator addBehavior:self.pushBehavior];
self.tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handTapGesture:)];
[self.view addGestureRecognizer:self.tapGesture];
- (void)handTapGesture:(UITapGestureRecognizer *)gesture{
CGPoint point = [gesture locationInView:self.view];
CGPoint origin = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds));
CGFloat distance = sqrtf(powf(point.x-origin.x, 2.0) + powf(point.y-origin.y, 2.0));
CGFloat angle = atan2(point.y-origin.y, point.x-origin.x);
distance = MIN(distance, 100.0);
[self.pushBehavior setMagnitude:distance/100.0];
[self.pushBehavior setAngle:angle];
[self.pushBehavior setActive:true];
}
物體屬性
物體
都有很多的屬性楚堤,通過(guò)對(duì)其配置疫蔓,可以達(dá)到不同的效果含懊,下面是一些常用的屬性:
屬性 | 描述 |
---|---|
elasticity | 表示與其他物體碰撞時(shí)的彈性,取值0-1衅胀,0表示沒(méi)有彈性岔乔,1表示反彈作用力與碰撞作用力相等 |
allowsRotation | 指定物體在受力時(shí)是否會(huì)旋轉(zhuǎn),默認(rèn)YES |
angularResistance | 旋轉(zhuǎn)助力滚躯,值越大旋轉(zhuǎn)下降得越快雏门,取值為0-CGFLOAT_MAX |
density | 物體的密度,調(diào)整密度會(huì)影響重力和碰撞的效果掸掏。默認(rèn)情況下茁影,100x100的物體質(zhì)量為1,100x200為2 |
friction | 物體之間的滑動(dòng)阻力丧凤,0表示沒(méi)有摩擦力募闲,1表示摩擦力很大 |
resistance | 空氣阻力,取值為0-CGFLOAT_MAX息裸,0表示沒(méi)有空氣阻力蝇更,1表示一旦其他作用力消失,物體就會(huì)停止 |
總結(jié)
文章代碼Demo點(diǎn)這里
UIDynamicAnimator還有代理方法和其他的小方法,真正發(fā)揮它的作用力的是你的創(chuàng)意恃慧,有好的ideal就動(dòng)手?jǐn)]吧腿箩!