2014-01-19 42 views
4

我目前4個圖像之間的動畫是這樣的:創建流暢的動畫與動畫的UIImageView

UIImageView *tom3BeforeImage; 
tom3Images = [NSArray arrayWithObjects: [UIImage imageNamed:@"floortom_before1.png"],[UIImage imageNamed:@"floortom_before2.png"],[UIImage imageNamed:@"floortom_before3.png"],[UIImage imageNamed:@"floortom_before4.png"], nil ]; 
tom3BeforeImage.animationImages = tom3Images; 
tom3BeforeImage.animationDuration = 0.75; 
[tom3BeforeImage startAnimating]; 

它工作正常,除了動畫的圖像之間波動。我需要的持續時間正好是0.75秒,所以加速它不是一個選項。

什麼是使動畫在圖像之間更平滑的最佳方式,像是在每個圖像變化之間進行混合?

謝謝!

+0

另一種方法是手動地改變圖像I,E。改變.image屬性。您可以使用計時器更改圖像屬性。 – iCoder

回答

4

如果您使用的是基於UIImageView的動畫幀,並且動畫必須是0.75秒,那麼我所知道的使其更平滑的唯一方法是創建更多幀。嘗試30幀/秒,或約22幀。這應該讓運動非常順利。

如果你想在幀之間進行某種交叉融合,那麼你將無法使用UIView幀動畫。你必須使用UIView塊動畫(使用animateWithDuration:animations:或其堂兄弟)。

你可以在你的幀之間創建一個序列,其中序列的總持續時間是0.75秒。每個轉換都會觸發完成塊中的下一個轉換。

事情是這樣的:

你需要2個圖像視圖,堆放在彼此的頂部。你會同時淡出一個和另一個。你需要在兩者上設置不透明標誌爲NO。

讓我們稱之爲tom3BeforeImage1和tom3BeforeImage2

添加一個int實例變量imageCount,讓您的圖像,tom3Images的陣列,和實例變量:

- (void) animateImages; 
{ 
    CGFloat duration = .75/([tom3Images count] -1); 

    //Start with the current image fully visible in tom3BeforeImage1 
    tom3BeforeImage1.image = tom3Images[imageCount]; 
    tom3BeforeImage1.alpha = 1.0; 

    //Get the next image ready, at alpha 0, in tom3BeforeImage2 
    tom3BeforeImage2.image = tom3Images[imageCount+1]; 
    tom3BeforeImage2.alpha = 0; 
    imageCount++ 

    [UIView animateWithDuration: duration 
    delay: 0 
    options: UIViewAnimationOptionCurveLinear 
    animations: 
    ^{ 
     //Fade out the current image 
     tom3BeforeImage1.alpha = 0.0; 

     //Fade in the new image 
     tom3BeforeImage2.alpha = 1.0; 
    } 
    completion: 
    ^{ 
    //When the current animation step completes, trigger the method again. 
    if (imageCount < [tom3Images count] -1) 
     [self animateImages]; 
    } 
    ]; 
} 

注意,我撞了上面的代碼在論壇編輯中沒有足夠的咖啡。它可能包含語法錯誤,甚至可能有邏輯問題。這只是爲了讓你思考如何去做。

編輯#2:

我不知道爲什麼,但我決定充實了這一點成爲一個完全成熟的示例項目。上面的代碼在調試後可以很好地工作,但是由於它在同一時間淡出一個圖像並且正在消失另一個圖像,兩個圖像視圖背後的背景都會顯示出來。

我重新編寫了一個邏輯,只將頂部圖像淡入淡出。它將第一幀放在頂部圖像視圖中,將第二幀放入底部圖像視圖中,然後淡出頂部圖像視圖。

該項目在github上,名爲Animate-Img。 (鏈接)

然後,它安裝在頂部圖像視圖中的第三幀和消失它IN,

然後,它安裝第四成名於底圖像視圖和淡出頂部以暴露底部等,等等

我結束了創建一個通用方法

- (void) animateImagesWithDuration: (CGFloat) totalDuration 
          reverse: (BOOL) reverse 
         crossfade: (BOOL) doCrossfade 
       withCompletionBlock: (void (^)(void)) completionBlock; 

它將動畫一組圖像,爲一對形象的意見,可選扭轉動畫一旦它完成。一旦完成動畫,就會調用一個完成塊。

動畫按鈕實際上調用重複整個動畫序列的方法。目前設置爲只運行一次,但如果需要,改變常量將使程序重複整個序列。

+0

謝謝鄧肯。你能否給我一個例子或者指點我交叉解散的正確方向? – codeman

+0

@codeman,我用一些(未經測試的)代碼更新了我的答案。它需要調試。 –

+0

@codeman,我在github上添加了一個示例項目(鏈接在我原來的帖子中) –

2

我確實需要用圖像陣列進行動畫。最初當我使用imageview的animationImages屬性時,我得到了所需的動畫,但圖像之間的轉換並不平滑,然後我使用CAKeyframeAnimation實現了平滑過渡,捕獲的是使用timingFunction以及正確的calculationMode。我不知道這是確切的問題的答案,但這是爲了使動畫更加平滑的一種方式, 下面是該

代碼有關的計算模式的詳細信息,請參閱Apple Documentation

- (void) animate 
{ 
    NSMutableArray * imageArray = [[NSMutableArray alloc] init]; 

    int imageCount = 8; 

    for (int i=0; i<=imageCount; i++) { 
     [imageArray addObject:(id)[UIImage imageNamed:[NSString stringWithFormat:@「image%d」,i]].CGImage]; 
    } 

    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"contents"]; 
    animation.calculationMode = kCAAnimationLinear;// Make sure this is kCAAnimationLinear or kCAAnimationCubic other mode doesnt consider the timing function 
    animation.duration = 8.0; 
    animation.values = imageArray; 
    animation.repeatCount = 1; // Change it for repetition 
    animation.removedOnCompletion = NO; 
    animation.fillMode = kCAFillModeForwards; // To keep the last frame when animation ends 
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
    [imageView.layer addAnimation:animation forKey:@"animation"]; 
} 

更新 - 夫特3

func animate() { 
    var imageArray = [CGImage]() 
    let imageCount: Int = 3 
    for i in 0...imageCount { 
     imageArray.append((UIImage(named: String(format:"image\(i)"))?.cgImage!)!) 
    } 
    let animation = CAKeyframeAnimation(keyPath: "contents") 
    animation.calculationMode = kCAAnimationLinear 
    // Make sure this is kCAAnimationLinear or kCAAnimationCubic other mode doesnt consider the timing function 
    animation.duration = CFTimeInterval(floatLiteral: 8.0) 
    animation.values = imageArray 
    animation.repeatCount = 1 
    // Change it for repetition 
    animation.isRemovedOnCompletion = false 
    animation.fillMode = kCAFillModeForwards 
    // To keep the last frame when animation ends 
    animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) 
    animImageView.layer.add(animation, forKey: "animation") 
} 
+1

Works很好,非常感謝。 – Kumar