4

好吧,所以我試圖做一個'輪財富'類型的效果與輪形狀在iOS中,我可以抓住和旋轉一個輪子。我現在可以拖動輪子並旋轉輪到我的心臟的內容,但釋放我的手指後,它就會停止。我需要應用一些動量或慣性來模擬車輪自然旋轉。試圖讓我的頭在模擬動量/慣性與UIRotationGestureController

我已經準備好了速度計算,所以當我擡起手指時,速度(最小值1到最大值100之間)的範圍爲1到1800以上(在我最難的動作!),現在我只是試圖確定如何將該速度轉換爲適用於該對象的實際旋轉角度,以及如何隨着時間推移減慢速度。

我最初的想法是這樣的:開始在一個循環中以與賦予的速度相同的速度旋轉整個圓,然後在隨後的每次旋轉中,將速度減慢一小部分。這應該會產生這樣的效果:更難旋轉的速度更快,並且需要更長的時間才能減慢速度。

我不是數學家,所以我的方法可能是錯誤的,但如果任何人有任何提示,我可以如何使這個工作,至少在基本狀態,我會很感激。這裏有一個非常有用的答案:iPhone add inertia/momentum physics to animate "wheel of fortune" like rotating control,但它更理論化,缺乏關於如何將計算速度應用於對象的實用信息等。我想我在這裏也需要一些動畫幫助。

編輯:我也需要解決,如果他們拖動輪順時針或逆時針。

非常感謝!

回答

1

我已經寫了一些類似於我的程序一點,但我的情況,我認爲是一個比較複雜的,因爲我在3D旋轉:https://itunes.apple.com/ua/app/bit/id366236469?mt=8

基本上我做的是我設置了一個NSTimer調用定期一些方法。我只是想方向和速度來創建一個旋轉矩陣(正如我所說,3D有點難看:P),並且將速度乘以小於1的某個數字,從而使其下降。乘法而不是減法的原因是,如果來自用戶的旋轉是兩倍的難度,您不希望對象旋轉兩次,因爲這變得煩人,等待我找到。

至於確定車輪正在旋轉的方向,只需將它存儲在touchesEnded:withEvent:方法中,您可獲取所有信息。既然你說你已經有了跟蹤工作,只要用戶把手指放下,這應該是顯而易見的。

我有3D是一樣的東西:

// MyView.h 
@interface MyView : UIView { 
    NSTimer *animationTimer; 
} 
- (void) startAnimation; 
@end 


// MyAppDelegate.h 
@implementation MyAppDelegate 

- (void) applicationDidFinishLaunching:(UIApplication *)application { 
    [myView startAnimation]; 
} 

@end 

// MyView.m 
GLfloat rotationMomentum = 0; 
GLfloat rotationDeltaX = 0.0f; 
GLfloat rotationDeltaY = 0.0f; 

@implementation MyView 
- (void)startAnimation { 
    animationTimer = [NSTimer scheduledTimerWithTimeInterval:(NSTimeInterval)((1.0/60.0) * animationFrameInterval) target:self selector:@selector(drawView:) userInfo:nil repeats:TRUE]; 
} 

- (void) drawView:(id)sender { 
    addRotationByDegree(rotationMomentum); 
    rotationMomentum /= 1.05; 
    if (rotationMomentum < 0.1) 
     rotationMomentum = 0.1; // never stop rotating completely 
    [renderer render]; 
} 

- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event 
{ 
} 

- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event 
{ 
    UITouch *aTouch = [touches anyObject]; 
    CGPoint loc = [aTouch locationInView:self]; 
    CGPoint prevloc = [aTouch previousLocationInView:self]; 

    rotationDeltaX = loc.x - prevloc.x; 
    rotationDeltaY = loc.y - prevloc.y; 

    GLfloat distance = sqrt(rotationDeltaX*rotationDeltaX+rotationDeltaY*rotationDeltaY)/4; 
    rotationMomentum = distance; 
    addRotationByDegree(distance); 

    self->moved = TRUE; 
} 

- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event 
{ 
} 

- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event 
{ 
} 

我已經離開了addRotationByDegree功能,但它的作用是,它使用全局變量rotationDeltaX和rotationDeltaY和旋轉矩陣適用於已存儲矩陣,然後保存結果。在您的例子,你可能想要的東西要簡單得多,就像(我現在假設,只有在X方向運動旋轉的車輪):

- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event 
{ 
    UITouch *aTouch = [touches anyObject]; 
    CGPoint loc = [aTouch locationInView:self]; 
    CGPoint prevloc = [aTouch previousLocationInView:self]; 

    GLfloat distance = loc.x - prevloc.x; 
    rotationMomentum = distance; 
    addRotationByDegree(distance); 

    self->moved = TRUE; 
} 

void addRotationByDegree(distance) { 
    angleOfWheel += distance; // probably need to divide the number with something reasonable here to have the spin be nicer 
} 
+0

這是一個有趣的小應用程序!我一定會諮詢它nect時間我決定我是否想要一個浴缸或淋浴,或者其他東西:) 這確實看起來像我所需要的(儘管在3D中)。對不起,我很痛苦 - 你能給我一些更具體的細節嗎? 我不太確定旋轉矩陣是什麼,我不是任何方式的代數專家。 – Luke 2013-02-15 16:52:18

+0

我很努力去理解我首先應用於對象的旋轉方式。例如,我不想讓它旋轉特定數量的弧度/度數,我希望它可以無限旋轉,然後我可以按照您的建議進行操作,並嘗試在每次後續旋轉時減慢它的速度。我如何開始這個過程,初始旋轉?我所擁有的是表示速度的單個浮點值。 – Luke 2013-02-15 16:53:10

+0

「我想讓它無限旋轉」你呢? – Vinzzz 2013-02-18 09:26:26

1

這將是一個粗略的答案,因爲我沒有任何詳細的例子在手。

如果你已經有速度時,你已經提起你的手指,那麼它不應該很難。 你擁有的速度是像素每秒或類似的東西。 首先,您需要將該線速度轉換爲角速度。這可以通過知道圓的周長2*PI*radius然後做2*PI/perimeter*velocity來獲得每秒弧度的角速度。

如果你的車輪在它的軸上沒有任何摩擦力,它將以這個速度永遠運行。那麼,你可以爲這個摩擦仲裁一個數值,這是一個加速度,可以表示爲角速度的每秒像素平方或弧度每秒平方。那麼這只是一個角速度除以這個角加速度的問題,你可以得到時間直到停止。

使用動畫時間,您可以使用方程finalAngle = initialAngle + angularSpeed*animationTime - angularAcceleration/2*animationTime*animationTime來獲取輪子將在動畫結束時的最終角度。然後,只需在變形上做一個動畫,並按照該角度旋轉它,然後說出你的動畫應該緩解。

這應該看起來夠實際。如果沒有,則需要根據上面公式中的一些樣本爲輪子的旋轉屬性提供動畫路徑。