簡體   English   中英

使用CABasicAnimation多次旋轉UIImageView

[英]Using CABasicAnimation to rotate a UIImageView more than once

我正在使用CABasicAnimation將UIImageView順時針旋轉90度,但是我需要讓它在初始旋轉90度后從其位置再旋轉90度。

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
animation.duration = 10;
animation.additive = YES;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.fromValue = [NSNumber numberWithFloat:DEGREES_TO_RADIANS(0)];
animation.toValue = [NSNumber numberWithFloat:DEGREES_TO_RADIANS(90)];
[_myview.layer addAnimation:animation forKey:@"90rotation"];

使用上面的代碼最初可以工作,圖像保持90度角。 如果我再次調用它使其旋轉90度,則動畫將從跳回0並旋轉90度而不是90至180度開始。

我的印象是animation.additive = YES; 會導致其他動畫將當前狀態用作起點。

有任何想法嗎?

tl; dr:很容易濫用removeOnCompletion = NO並且大多數人沒有意識到這樣做的后果。 適當的解決方案是“實際”更改模型值。


首先:我不是要判斷你或對你卑鄙。 我一遍又一遍地看到同樣的誤解,我明白了為什么會發生。 通過解釋為什么會發生這種情況,我希望遇到同樣問題並看到此答案的每個人都了解他們的代碼在做什么。

什么地方出了錯

我的印象是animation.additive = YES; 會導致其他動畫將當前狀態用作起點。

這是真的,這正是發生的情況。 從這個意義上說,計算機很有趣。 他們總是完全按照您告訴他們的內容,而不是您想要他們做什么。

removeOnCompletion = NO可能是個bit子

在您的情況下,反派是這一行代碼:

animation.removedOnCompletion = NO;

動畫完成后,經常會濫用它來保留動畫的最終值。 唯一的問題是,它是通過不從視圖中刪除動畫來發生的。 “核心動畫”中的動畫不會更改其設置動畫的基礎屬性,而只是在屏幕上對其進行動畫處理。 如果在動畫過程中查看實際值,您將永遠看不到它的變化。 取而代之的是,動畫在所謂的表示層上工作。

通常,動畫完成后,將其從圖層中刪除,表示層消失,模型層再次出現在屏幕上。 但是,當您將動畫附加到圖層時,所有內容在屏幕上看起來都應該看起來一樣,但是您引入了屬性所說的變換與圖層在屏幕上看起來如何旋轉之間的區別。

正如您所說,將動畫配置為可疊加時,意味着將from和to值添加到現有值中。 問題在於該屬性的值為0。您永遠不會對其進行更改,而只是對其進行動畫處理。 下次嘗試將該動畫添加到同一層時,該值仍不會更改,但該動畫將完全按照其配置進行操作:“從模型的當前值進行附加動畫”。

解決方案

跳過那行代碼。 但是結果是旋轉不固定。 使其堅持下去的更好方法是更改​​模型。 在對旋轉進行動畫處理之前,設置旋轉的新的最終值,以使模型在刪除動畫時看起來像應該的樣子。

byValue就像魔術

CABasicAnimation上有一個非常方便的屬性(我將要使用),該屬性稱為byValue ,可用於制作相對動畫。 它可以結合兩種toValuefromValue做許多不同種類的動畫。 不同的組合都在其文檔中指定了(在本節下面)。 我要使用的組合是:

byValuetoValue是非nil 之間進行插值(toValue - byValue)toValue

一些實際的代碼

顯式的toValue為0時,動畫發生在“ currentValue-byValue”到“ current value”之間。 通過更改模型,第一個當前值是最終值。

NSString *zRotationKeyPath = @"transform.rotation.z"; // The killer of typos

// Change the model to the new "end value" (key path can work like this but properties don't)
CGFloat currentAngle = [[_myview.layer valueForKeyPath:zRotationKeyPath] floatValue];
CGFloat angleToAdd   = M_PI_2; // 90 deg = pi/2
[_myview.layer setValue:@(currentAngle+angleToAdd) forKeyPath:zRotationKeyPath]; 

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:zRotationKeyPath];
animation.duration = 10;
// @( ) is fancy NSNumber literal syntax ...
animation.toValue = @(0.0);        // model value was already changed. End at that value
animation.byValue = @(angleToAdd); // start from - this value (it's toValue - byValue (see above))

// Add the animation. Once it completed it will be removed and you will see the value
// of the model layer which happens to be the same value as the animation stopped at.
[_myview.layer addAnimation:animation forKey:@"90rotation"];

小免責聲明

我沒有運行此代碼,但可以肯定的是它可以按預期運行,並且我沒有做任何錯別字。 如果我糾正了我。 整個討論仍然有效。

通過角度增量值請參閱我的代碼

static int imgAngle=0;
- (void)doAnimation
{
  CABasicAnimation *animation = [CABasicAnimation   animationWithKeyPath:@"transform.rotation.z"];
   animation.duration = 5;
  animation.additive = YES;
  animation.removedOnCompletion = NO;
  animation.fillMode = kCAFillModeForwards;
  animation.fromValue = [NSNumber numberWithFloat:DEGREES_TO_RADIANS(imgAngle)];
  animation.toValue = [NSNumber numberWithFloat:DEGREES_TO_RADIANS(imgAngle+90)];
 [self.imgView.layer addAnimation:animation forKey:@"90rotation"];

  imgAngle+=90;
  if (imgAngle>360) {
      imgAngle = 0;
  }
}

上面的代碼僅供參考。 未經測試

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM