2013-02-18 146 views
8

我有以下簡單的UIImageView動畫:停止動畫的UIImageView逐漸平穩

-(void) setupTheAnimation { 
    self.imgView.animationImages = imagesArr; 
    [self.imgView setAnimationRepeatCount:-1]; 
    self.imgView.animationDuration =0.9; 
    [self.imgView startAnimating]; 
    [self performSelector:@selector(stopTheAnimation) withObject:nil afterDelay:4.0]; 
} 

-(void) stopTheAnimation { 
    [self.imgView stopAnimating]; 
} 

但是當動畫停止,我不知道什麼是它停止在最後一幀我面對的一個問題!所以動畫的結局根本不流暢。

,所以我需要:

1)知道什麼是最後一幀處的動畫結束了,所以我把它作爲動畫的最後一個圖像,這導致了平穩停車。

2)逐漸停止該動畫,即在停止之前改變其持續時間以使其先減速並停止。

This is a link to the sample project

+1

好問題:) – 2013-02-18 14:03:24

+0

我想說這需要作爲一個自定義的動畫屬性實現在UIImageView的子類上,在這裏你重複地將圖層的內容設置爲圖像陣列中的圖像提供定時功能。不會太難,但我不認爲有可能通過'UIImageView'的'animationImages'來完成緩解效果。 – 2013-02-24 08:54:50

回答

2

我知道你的最初實現使用animationImages,但我不知道的方式來使用animationImages直接具有連續可變的持續時間。但是,這是一個非常簡單的功能來實現自己。如果你這樣做,那麼你可以在你的數組中的圖像之間編碼一個動態持續時間值。

在下面的代碼,我取代animationImages使用自定義步進功能,並動態調整後停止已被請求的持續時間。請注意,這與您的原始代碼有點不同,它指定了一段艱難的結束時間。此代碼指定齒輪旋轉應在何時開始開始減速。

如果你真的有一個硬動畫時期,你可以調整到stopTheAnimation來考慮你選擇的減速因素(我只是在減速期間每步增加10%的持續時間,直到步驟比給定的閾值):

// my animation stops when the step duration reaches this value: 
#define STOP_THRESHOLD_SECONDS 0.1f 
#define NUM_IMAGES 35 

@implementation ViewController 
{ 
    NSMutableArray *imagesArr; 
    int currentImage; 
    BOOL stopRequested; 
    NSTimeInterval duration; 
} 

-(void) setupTheAnimation { 

    stopRequested = NO; 
    currentImage = 0; 
    duration = 0.9f/NUM_IMAGES; 
    [self stepThroughImages]; 

    [self performSelector:@selector(stopTheAnimation) withObject:nil afterDelay:4.0]; 
} 

- (void) stepThroughImages { 

    self.imgView.image = [imagesArr objectAtIndex: currentImage]; 

    if (currentImage == NUM_IMAGES - 1) { 
     currentImage = 0; 
    } else { 
     currentImage++; 
    } 

    if (stopRequested && duration < STOP_THRESHOLD_SECONDS) { 
     // we're slowing down gradually 
     duration *= 1.1f; 
     dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)); 
     dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
      [self stepThroughImages]; 
     }); 
    } else if (!stopRequested) { 
     dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)); 
     dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
      [self stepThroughImages]; 
     }); 
    } 
} 

-(void) stopTheAnimation { 
    stopRequested = YES; 
} 
+0

真棒...非常感謝你。 – JAHelia 2013-02-25 06:36:51

+0

不客氣。我只注意到你的項目中實際上有36張圖像(0到35)。所以,也許你應該把我的代碼中的'NUM_IMAGES'改爲'36',因爲我從'0'迭代到'NUM_IMAGES - 1'。我認爲在你的'viewDidLoad'方法中初始化'imagesArr'的代碼有同樣的問題。它實際上並沒有加載'GearAnimation35 @ 2x.png'。 – Nate 2013-02-25 07:38:09

0

我只用塊知道這一點,但這裏是你如何做到這一點:

[UIImageView animateWithDuration:0.9f delay:0.0f options:UIViewAnimationOptionCurveEaseOut animations:^{ 

       // animate what you want 
       self.imgView.transform = CGAffineTransformMakeScale(1.0f, 1.0f); 

      } completion:^(BOOL finished){ 

       // animation is completed 
       self.imgView.image = image; 

      }]; 

選項「UIViewAnimationOptionCurveEaseOut」應該逐漸停止動畫。你可以與其他選項一起玩,看看效果。

+0

這不適用於我在問題中發佈的animationImages方法。 – JAHelia 2013-02-18 19:07:55

0

你的方法有一個問題:每秒幀數不是恆定的(你減慢時間)。

您確定需要動畫嗎?

如果您的動畫可以通過幾何(仿射)轉換來實現,那麼它會更好。

如果你的動畫可以用組合來實現:

  • 翻譯
  • 旋轉
  • 縮放

那麼這是一個仿射變換。

+1

如果他們從頭開始完成這項任務,我會100%同意。 3個齒輪中的每一個都可以是用仿射變換旋轉的單獨圖像。但是,由於他們已經得到了36張圖片,我可以說這可能是一個很好的工作(可能超出了*編程*和*圖形設計的範圍)。必須提取四個或五個單獨的圖像:背景,2/3檔位和邊框以放置在頂部。此外,齒輪移動的棘輪特性我認爲也可以使基於幀的動畫的輕微變化成爲可接受的。 – Nate 2013-02-24 21:34:29

+0

謝謝Nate。我沒有意識到這36個齒輪圖像,因爲這在原始問題中沒有提到。但是你的方式是可以接受的,但是最終的渲染質量仍然很差,因爲時間在給定的速度下被分離,並且你需要放慢速度。無論如何。 – 2013-02-25 07:32:52

+0

是的,你必須真正下載完整的項目才能看到,所以從單純的問題來看肯定不是很明顯:) – Nate 2013-02-25 07:34:42