2016-10-18 78 views
1

我使用CAKeyframeAnimation沿着CGPath爲箭頭設置動畫。除了當atan2'從0翻轉'到2π或反之亦然時,箭頭沿着路徑。在這種情況下,箭頭在繼續之前完成360°旋轉。如何避免旋轉動畫在2π邊界處跳動?

是否有任何方法來計算我的CAKeyframeAnimation的值,使箭頭總是旋轉最小的數量,以得到它的去向?

 let turnAnimation = CAKeyframeAnimation(keyPath: "transform.rotation") 
     turnAnimation.duration = 5 

     var values = [CGFloat]() 
     for i in 0..<points.count - 1 { 

      let point1 = points[i] 
      let point2 = points[i + 1] 
      let delta = point2 - point1 
      let value = atan2(delta.y, delta.x) 

      values.append(value) 
     } 

     turnAnimation.values = values 
     turnAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) 
     turnAnimation.repeatCount = Float.greatestFiniteMagnitude 
     arrowPointLayer.transform = CATransform3DMakeRotation(values.first!, 0, 0, 1) 
     arrowPointLayer.add(turnAnimation, forKey: "rotateArrow") 

編輯:更新基礎上的答案,但依然沒有完全工作:

let turnAnimation = CAKeyframeAnimation(keyPath: "transform.rotation") 
     turnAnimation.duration = 5 

     var rawValues = [CGFloat]() 
     var values = [CGFloat]() 
     for i in 0..<points.count - 1 { 

      let point1 = points[i] 
      let point2 = points[i + 1] 
      let delta = point2 - point1 
      let rawValue = atan2(delta.y, delta.x) 

      var value: CGFloat 

      if i == 0 { 
       value = 0 // we will apply this value from rawValues 
      } else { 
       let lastValue = rawValues.last! 
       value = rawValue - lastValue 
      } 

      if value < 0 { 
       value = .pi * 2 + value 
      } 

      rawValues.append(rawValue) 

      values.append(value) 
     } 

     for (i, p) in values.enumerated() { 
      print("\(rawValues[i]): \(p)") 
     } 

     turnAnimation.values = values 
     turnAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) 
     turnAnimation.repeatCount = Float.greatestFiniteMagnitude 
     turnAnimation.isAdditive = true 

     arrowPointLayer.transform = CATransform3DMakeRotation(rawValues.first!, 0, 0, 1) 
     arrowPointLayer.add(turnAnimation, forKey: "rotateArrow") 
+0

嗨,再次 - 我突然發現,問題可能是使用''transform.rotation''作爲關鍵路徑。蘋果建議不要那樣做。 – matt

+0

真的嗎?相反,只是「旋轉」? – buildsucceeded

+0

只是變換。您可以使用值函數來指定z旋轉。 – matt

回答

1

而不是使values絕對旋轉值的列表,使它的旋轉差異列表和設置動畫的isAdditivetrue。那樣,告訴箭頭哪個方向轉動和多少。

我測試過這樣的(在我的測試,v只是一些看法坐在我的界面):

let turnAnimation = CAKeyframeAnimation(keyPath: "transform.rotation") 
turnAnimation.duration = 5 
let values : [CGFloat] = [0,2,-1,2,-1,3,-3] 
turnAnimation.values = values 
turnAnimation.timingFunction = 
    CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) 
turnAnimation.isAdditive = true 
self.v.layer.add(turnAnimation, forKey: "rotateArrow") 

視圖表現完全按照我的預期。

+0

從概念上講,這太棒了!不幸的是,當我實現它時,箭頭完全停止旋轉::劃痕頭:: – buildsucceeded

+0

我不知道你的代碼看起來像什麼_now_。我只知道它最初的樣子。我向你保證它確實有效。我會添加一個簡單的例子作爲測試。 – matt

+0

謝謝!接受;我會找出我自己的錯誤... – buildsucceeded