2017-05-04 196 views
1

我有一個subclassed imageview,我想淡入,放大和旋轉,然後繼續旋轉,同時縮小和淡出。UIView動畫 - 旋轉和放大,然後旋轉並縮小比例

我正在使用帶有完成處理程序的UIView動畫塊來處理收縮。

問題是這不是流動的動畫。在完成處理程序運行之前,動畫在再次運行之前停止。我需要它是動畫的一個很好的「一舉一動」。下面

代碼:

let duration: TimeInterval = 3.0 
    let rotate = CGAffineTransform(rotationAngle: CGFloat(Double.pi)) 


    UIView.animate(withDuration: duration * 3, delay: 0, options: [.curveLinear], animations: { 
     // initial transform 
     self.alpha = 0 
     self.transform = CGAffineTransform(scaleX: 0.1, y: 0.1) 
     // initial spin for duration of animaton 
     UIView.animate(withDuration: duration * 3, delay: 0.0, options: [.curveLinear], animations: { 
      self.transform = rotate 
     }, completion: nil) 

     // scaling and fading 
     UIView.animate(withDuration: duration, delay: 0, options: [.curveLinear], animations: { 
      UIView.setAnimationRepeatCount(3) 
      self.transform = self.transform.scaledBy(x: 0.8, y: 0.8) 
      self.alpha = 1 
     }) { (true) in 
      UIView.animate(withDuration: duration, animations: { 
       UIView.setAnimationRepeatCount(3) 
       self.transform = self.transform.scaledBy(x: 0.1, y: 0.1) 
       self.alpha = 0 
      }) 
     } 
    }, completion: nil) 

我怎樣才能讓動漫旋轉整個時間而衰落和縮減下來,淡出前擴大?整個動畫應持續3秒,並重復3次。謝謝。 ()

+0

你看着關鍵幀動畫? –

+0

我同意Donnovan King的觀點......你應該從UIView動畫級下降到通過Core Animation直接完成的關鍵幀動畫。這將使您的整個動畫連續循環。 –

+0

多諾萬和斯科特 - 通過關鍵幀動畫,你的意思是用cabasicanimation動畫? – Joe

回答

3

爲了您的修改請求我的代碼我正在擴展你已經看到使用塊動畫。正如一些人所說,關鍵幀動畫可能會更好,不管這是什麼想法。

創建一個通過轉換視圖來旋轉整個時間的動畫。 創建另一個基於當前變換(旋轉)進行縮放和衰落的動畫。在這個過程中,我剛剛創建了一些變量,以允許您自定義(和重複)動畫的各個部分。我弄清楚了一些事情要清楚,並且知道我可以重構寫更簡潔的東西。

下面是代碼

import UIKit 

class OrangeView: UIView { 



override func layoutSubviews() { 
    super.layoutSubviews() 

    let duration: TimeInterval = 9.0 

    self.transform = CGAffineTransform.identity 

    // initial transform 
    self.alpha = 1 
    self.transform = CGAffineTransform(scaleX: 0.1, y: 0.1) 

    // start rotation 
    rotate(duration: duration) 

    // scaling and fading 
    scaleUpAndDown(desiredRepetitions: 3, initalDuration: duration) 


    } 

func rotate(duration: TimeInterval) { 
       UIView.animate(withDuration: duration/2.0, 
           delay: 0.0, 
           options: [.curveLinear], animations: { 
           let angle = Double.pi 
           self.transform = self.transform.rotated(by: CGFloat(angle)) 
       }, completion: {[weak self] finished in 
    guard let strongSelf = self else { 
    return 
    } 
    if finished && 
    strongSelf.transform != CGAffineTransform.identity { 
    strongSelf.rotate(duration: duration) 
    } else { 
    // rotation ending 
    } 
}) 

    } 

func scaleUpAndDown(timesRepeated: Int = 0, desiredRepetitions: Int, initalDuration: TimeInterval) { 

guard timesRepeated < desiredRepetitions, 
    desiredRepetitions > 0, initalDuration > 0 else { 
    self.transform = CGAffineTransform.identity 
    return 
} 
let repeatedCount = timesRepeated + 1 

let scalingDuration = initalDuration/2.0/Double(desiredRepetitions) 

UIView.animate(withDuration: scalingDuration, 
       delay: 0.0, 
       animations: { 
       let desiredOriginalScale: CGFloat = 0.8 

       let scaleX = abs(CGAffineTransform.identity.a/self.transform.a) * desiredOriginalScale 
       let scaleY = abs(CGAffineTransform.identity.d/self.transform.d) * desiredOriginalScale 

       self.transform = self.transform.scaledBy(x: scaleX, y: scaleY) 
       self.alpha = 1 
       }) { (true) in 
       UIView.animate(withDuration:scalingDuration, 
           delay: 0.0, 
           animations: { 

           let desiredOriginalScale: CGFloat = 0.1 

           let scaleX = abs(CGAffineTransform.identity.a/self.transform.a) * desiredOriginalScale 
           let scaleY = abs(CGAffineTransform.identity.d/self.transform.d) * desiredOriginalScale 
            self.transform = self.transform.scaledBy(x: scaleX, y: scaleY) 
            self.alpha = 0 
       }) { finshed in 
        self.scaleUpAndDown(timesRepeated: repeatedCount, desiredRepetitions: desiredRepetitions, initalDuration: initalDuration); 
       } 
       } 

    } 

} 

最後這裏是另一個gif動畫

enter image description here

+0

你搖滾!這太棒了!!!感謝丹尼的幫助 – Joe

+0

樂意幫忙!有趣的是...... transform.rotated(by:CGFloat(angle))'。如果你的角度是2π,360度,那麼變換將會用最短的路徑完成,並且因爲它已經在結束變換中,所以不會發生任何事情。因此,爲了獲得完整的旋轉,我們旋轉π(180度),然後完成後,再次在完成塊中旋轉180度。 – DannyJi

0

嘗試使用CGAffineTransformConcat

CGAffineTransform scale = CGAffineTransformMakeScale(0.8, 0.8); 
    self.transform = CGAffineTransformConcat(CGAffineTransformRotate(self.transform, M_PI/2), scale); 
+0

通過在現有變換上調用像scaledBy這樣的函數,它已經在執行連接。 –

2

enter image description here

我看到旋轉輕微的口吃在onCompletion的開始。

我創建了一個縮減代碼(如下圖所示的藍色視圖)和橙色視圖中的變體。這是從模擬器中提取出來的,並變成了動畫GIF,因此速度變慢了。橙色視圖繼續旋轉,因爲完整的變換隻是縮小。

這是layoutSubviews()爲橙色查看

覆蓋FUNC layoutSubviews(){ super.layoutSubviews()

let duration: TimeInterval = 3.0 
let rotate = CGAffineTransform(rotationAngle: CGFloat(Double.pi)) 

// initial transform 
self.alpha = 0 
self.transform = CGAffineTransform(scaleX: 0.1, y: 0.1) 

// initial spin for duration of animaton 
UIView.animate(withDuration: duration, 
       delay: 0.0, 
       options: [.curveLinear], 
       animations: { 
        self.transform = rotate; 
       }, 
       completion: nil) 
// scaling and fading 
UIView.animate(withDuration: duration/2.0, animations: { 
    self.transform = self.transform.scaledBy(x: 0.8, y: 0.8) 
    self.alpha = 1 
}) { (true) in 
    UIView.animate(withDuration: duration/2.0, animations: { 
    self.transform = self.transform.scaledBy(x: 0.1, y: 0.1) 
    self.alpha = 0 
    }) 
} 

}

+0

這太棒了!並感謝您花時間創建最終結果的gif!有沒有辦法爲你的橙色動畫添加重複計數?我嘗試將setAnimationRepeatCount(3)添加到縮放和淡入淡出區塊,但它將動畫剪成3「位」 – Joe

+0

我已經將您的答案標記爲正確,因爲它符合我的要求。重複動畫3倍不在我原來的問題範圍內,但如果你可以幫助獲得橙色視圖動畫重複3倍,這將不勝感激:)我得到非常奇怪的結果添加setAnimationRepeatCount在您的塊。 – Joe

+0

你是否想在3秒的時間內重複整個動畫3次?或者你是否想要將整個動畫的持續時間延長到9秒以便動畫重複(旋轉和縮放/淡入淡出)? – DannyJi