2.Popping筆記--Decay Animation

Popping筆記。Github上搜索"Popping"即可下載源代碼。

Decay Animation


首先分析動畫。

1.屏幕中心一個圓。

2.拖動圓,圓會運動并逐漸減速直到停止。

3.在圓運動的過程中,如果點擊圓,圓會立即停到點擊的地方。

4.如果圓碰到屏幕邊緣,會立即彈回到屏幕中點,并且感覺有一些彈性。

這個動畫很簡單,我們來看源代碼。

打開DecayViewController.m。

addDragView方法的主要是構(gòu)造我們的圓,并且設(shè)置點擊圓時候的處理方法和進行pan手勢所使用的方法。有一點需要注意的是dragView是一個UIControl,如果用的是UIView,則沒有addTarget:action:這個方法。UIControl是UIView的子類,實現(xiàn)了更多的功能,比如剛才我們所說的。

touchDown:方法很簡單,如果用戶點擊了圓,那么就移除這個圓的圖層的所有pop動畫,這也是我們在最開始時候分析的第3點的原因。

接下來看handlePan:方法。我們想一下,這個方法肯定是想要讓這個圓跟著我們的手指(鼠標(biāo))走,那么圓的位置該如何計算呢?

很簡單,圓的位置 = 圓現(xiàn)在的位置 + 手指在屏幕上滑動的距離。

所以首先我們得到手指滑動的距離,recognizer有很方便的方法返回一個CGPoint的值,分別代表x,y方向上平移的距離。有了手指滑動的距離,我們就可以設(shè)置圓的位置了。recognizer有一個view的屬性可以得到它所監(jiān)聽的對象,也就是dragView。我們將drageView的中點設(shè)置成其原來的位置+平移的距離,就像剛才說的那樣。

注意:

[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];

這行很重要。在每次移動的時候我們都要將recognizer的x,y方向上的translation設(shè)置成0,否則在下一次平移的時候translation就會疊加,我們的圓會直接飛出屏幕,因為這次移動不僅包含了這次平移的距離,還包含了以前平移的距離。

可以注意到如果我們手指一直在圓上,并不會出現(xiàn)減速效果,只有手指離開圓,即結(jié)束了pan的手勢,那么圓開始減速運動。接下來這行代碼就是解釋這一現(xiàn)象的:判斷recognizer的狀態(tài),如果已經(jīng)結(jié)束(即手指離開了屏幕,不再拖動圓),那么給圓加上一個POPDecayAnimation動畫。

if(recognizer.state == UIGestureRecognizerStateEnded) {
    CGPoint velocity = [recognizer velocityInView:self.view];
    POPDecayAnimation *positionAnimation = [POPDecayAnimation animationWithPropertyNamed:kPOPLayerPosition];
    positionAnimation.delegate = self;
    positionAnimation.velocity = [NSValue valueWithCGPoint:velocity];
    [recognizer.view.layer pop_addAnimation:positionAnimation forKey:@"layerPositionAnimation"];
}

首先得到手指在屏幕上的移動速度,接著創(chuàng)建POPDecayAnimation動畫,設(shè)置其速度為剛才得到的速度。那么設(shè)置動畫的delegate是因為什么呢?

看看我們在開始的分析的第4點你可能就會明白了。我們需要判斷每次移動的時候圓是不是超出邊界了。POP為我們提供了一個代理方法:

- (void)pop_animationDidApply:(POPDecayAnimation *)anim

動畫的每一幀都會調(diào)用這個方法,這也正是我們需要的,因為我們需要時時刻刻都注意圓是否超出邊界了。

- (void)pop_animationDidApply:(POPDecayAnimation *)anim
{
    BOOL isDragViewOutsideOfSuperView = !CGRectContainsRect(self.view.frame, self.dragView.frame);
    if (isDragViewOutsideOfSuperView) {
        CGPoint currentVelocity = [anim.velocity CGPointValue];
        CGPoint velocity = CGPointMake(currentVelocity.x, -currentVelocity.y);
        POPSpringAnimation *positionAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPosition];
        positionAnimation.velocity = [NSValue valueWithCGPoint:velocity];
        positionAnimation.toValue = [NSValue valueWithCGPoint:self.view.center];
        [self.dragView.layer pop_addAnimation:positionAnimation forKey:@"layerPositionAnimation"];
    }
}

在動畫的每一幀,我們需要判斷是否出界。

CGRectContainsRect(rect1,rect2)顧名思義,判斷rect2是否在rect1中,返回一個BOOL值。
一旦dragView不在self.view中了,我們就讓dragView回到view的中點,具體做法是:

得到currentVelocity(就是最開始手指移動的速度?),接著得到velocity:

    CGPoint velocity = CGPointMake(currentVelocity.x, -currentVelocity.y);

這句我也不是很懂,為什么要這樣做有沒有朋友可以指教一下?3QQQQ

接著創(chuàng)建POPSpringAnimation,設(shè)置velocity和toValue。

這里有一點需要注意,在我自己寫代碼的時候因為這個馬虎浪費了很多時間。。那就是我們剛才創(chuàng)建的decay animation的key和現(xiàn)在創(chuàng)建的spring animation的key需要保持一致。其實道理很簡單:我們首先創(chuàng)建了decay animation,我們希望圓一碰壁就彈回,即使用spring animation,但是有的時候decay animation還未結(jié)束就已經(jīng)碰壁,如果這兩個key不一樣,則spring animation需要等待decay animation結(jié)束才能執(zhí)行,這也是為什么圓會出屏幕一段時間然后彈回屏幕中點。正確的做法是我們將兩者的key設(shè)置成相同的,我的理解是:首先執(zhí)行decay animation,一旦圓碰壁了,我們添加spring animation,因為兩者是相同的key意思就是在原來動畫的基礎(chǔ)上變換成新的動畫,所以圓會馬上回到中點。而不是相同的key則相當(dāng)于創(chuàng)建了兩個完全不同的動畫,那么就需要一個結(jié)束另一個才能執(zhí)行,所以圓會一直等到decay結(jié)束才能spring。


在這個例子之前我對velocity和toValue屬性并不是很理解,現(xiàn)在有了一些新的理解:

并不是每一個動畫都需要toValue,比如說我們這個decay的例子,我們不需要設(shè)置toValue,只需要給decay animation一個velocity,它會自己根據(jù)這個速度來減速。

同樣的,在我們第一個例子shake button這個方法里面,我們創(chuàng)建了一個spring animation,沒有設(shè)置其toValue,而是給這個動畫一個velocity讓其根據(jù)這個速度移動。

所以我的理解是:toValue是我們給定一個目的地,是精確的。而velocity是我們給定一個速度讓其根據(jù)這個速度走,而究竟在哪一點停下來(decay animation),是遠是近(spring animation,時間不變,速度越快走的越遠),都要根據(jù)這個velocity。如果既設(shè)置toValue又設(shè)置velocity,則是到達目的地的快慢不同。這只是自己的理解,可能有不準(zhǔn)確的地方,希望不吝賜教。

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

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

  • 在iOS中隨處都可以看到絢麗的動畫效果,實現(xiàn)這些動畫的過程并不復(fù)雜,今天將帶大家一窺ios動畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,688評論 6 30
  • 在iOS中隨處都可以看到絢麗的動畫效果,實現(xiàn)這些動畫的過程并不復(fù)雜,今天將帶大家一窺iOS動畫全貌。在這里你可以看...
    F麥子閱讀 5,262評論 5 13
  • 目錄 ** UIView 動畫 ** ** Core Animation ** ** FaceBook POP動畫...
    方向_4d0d閱讀 1,814評論 0 3
  • 書寫的很好,翻譯的也棒!感謝譯者,感謝感謝! iOS-Core-Animation-Advanced-Techni...
    錢噓噓閱讀 2,428評論 0 6
  • 我們寫的應(yīng)用程序往往都不是靜態(tài)的,因為它們需要適應(yīng)用戶的需求以及為執(zhí)行各種任務(wù)而改變狀態(tài)。 在這些狀態(tài)之間轉(zhuǎn)換時,...
    sunmumu1222閱讀 837評論 0 2

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