2016-04-03 13 views
0

我有一個關鍵幀動畫來顯示Swift中的卡片處理效果。如果您按下按鈕,我使用第二個動畫(使用.BeginFromCurrentState ...)取消交易。這對簡單的單視圖動畫有效。但是按下按鈕後,這裏會有2-10秒的延遲,大概在每次取消動畫運行時。有一種更簡單,更順暢的方式來達到我想要的效果(立即取消交易)。有效取消Swift中的關鍵幀動畫

下面的代碼片段,樹立交易的動畫:

let durationSlice = 1.0/Double(numCards*numPlayers+1) 
    var durationSliceStart : Double = 0 
    UIView.animateKeyframesWithDuration(FiveKings.ANIMATION_250MS*(Double(numCards)*Double(numPlayers)+1), delay: 0.0 , 
     options: [.CalculationModeCubic], 
     animations: { 
      for iCard in 0..<numCards { 
       durationSliceStart = Double(iCard*numPlayers) * durationSlice 
       //translate the cards off the pile and to each mini Hand (and they stay visible) 
       for iPlayer in 0..<numPlayers { 
        //Animate the card into view at the start of this set 
        UIView.addKeyframeWithRelativeStartTime(durationSliceStart+Double(iPlayer)*durationSlice, relativeDuration: 0.0, animations: { 
          pileCardViews[iCard*numPlayers + iPlayer].alpha = 1.0 
         }) 


        //add a random amount of translation and rotation to simulate messy cards 
        let messyX = CGFloat((drand48()-0.5) * MESSY_CARD_XY_OFFSET) * self.mDrawPile.bounds.width 
        let messyY = CGFloat((drand48()-0.5) * MESSY_CARD_XY_OFFSET) * self.mDrawPile.bounds.height 
        let messyRotation = CGFloat((drand48()-0.5) * MESSY_CARD_ANGLE) * 2.0 * 3.14 

        //convert the destination miniHand into the coordinates of mDrawPile 
        let miniHandLayout = self.mGame.players.getPlayer(iPlayer).miniHandLayout! 
        miniHandDestinationPoint = miniHandLayout.cardView.convertPoint(CGPoint(x: 0,y: 0), toView: self.mDrawPile) 
        UIView.addKeyframeWithRelativeStartTime(durationSliceStart+Double(iPlayer)*durationSlice, relativeDuration: durationSlice, animations: { 
         pileCardViews[iCard*numPlayers + iPlayer].transform = CGAffineTransformConcat(
          CGAffineTransformMakeRotation(3.14+messyRotation), 
          CGAffineTransformMakeTranslation(miniHandDestinationPoint.x + messyX, miniHandDestinationPoint.y + messyY)) 
         if iCard == 0 {miniHandLayout.cardView.alpha = 1.0} 
        }) 

       } 

      }//end iCard 
      //animate a card to the DiscardPile 
      let discardPileDestination = self.mDiscardPile.convertPoint(CGPoint(x: 0, y: 0), toView: self.mDrawPile) 
      UIView.addKeyframeWithRelativeStartTime(durationSliceStart+Double(numPlayers)*durationSlice, relativeDuration: durationSlice, animations: 
       { 
        pileCardViews[numCards*numPlayers].transform = CGAffineTransformMakeTranslation(discardPileDestination.x, discardPileDestination.y) 
        pileCardViews[numCards*numPlayers].alpha = 1.0 
      }) 
     }, 
     //completion block removes the added cards 
     completion: {(_ : Bool) in 
      //remove the added cards 
      for pcv in pileCardViews {pcv.removeFromSuperview()} 
      self.afterDealing() 
     } 
    )//end UIView.animateKeyFramesWithDuration 

下面是運行代碼,當你按下「跳過處理」按鈕:

if !mDealingPileCards.isEmpty { 
     for pcv in self.mDealingPileCards {pcv.stopAnimation()} //also seems to call completion handler 
     self.mDealingPileCards.removeAll(keepCapacity: true) 
     self.setShowHint(stringKey: "toDisableDealing", setShowHint: FiveKings.HandleHint.SET_AND_SHOW_HINT, hintLevel: GameDifficulty.MEDIUM) 
    } 

stopAnimation實施是UIView的擴展:

func stopAnimation() { 
    UIView.animateWithDuration(0.0, delay: 0.0, options: [.BeginFromCurrentState], 
     animations: { 
      self.alpha = 1.0 
      self.transform = CGAffineTransformIdentity 
     }, completion: nil) 
} 

編輯:我有tr ied使用...layer.removeAllAnimations但同樣的延遲問題發生,也許完成處理程序運行?

回答

1

要取消動畫,只需向所有正在動畫的圖層(或每個視圖的圖層)指定removeAllAnimations即可。您還需要確定您現在希望顯示該視圖的位置,但這是一個不同的問題(換句話說,您必須考慮實際上包含的取消內容)。

+0

是的,我已經試過了。同樣的問題發生 - removeAllAnimations完成時會有一段很長的停頓。 – Opus1217

+0

「在removeAllAnimations完成時有很長的停頓」真的嗎?你確定你沒有線程問題嗎? – matt

+0

在我上面發佈的代碼片段中,如果我用pcv.layer.removeAllAnimations()替換pcv.stopAnimation(),我在UI中獲得了相同的「拖延」。你能指點我能做些什麼來追蹤「線程問題」嗎?沒有其他事情發生。 – Opus1217

0

問題的直接答案(本身帶來另一個問題)是stopAnimation(調用另一個動畫使用.BeginFromCurrentState)或..layer.removeAllAnimations實際上會取消動畫。但是在我的情況下,在完成塊中進行了額外的UI工作,顯然直到預定時間才運行。換句話說,即使您單獨取消/移除關鍵幀動畫,完成塊也會延遲。