簡體   English   中英

如何在預先轉換的UIView上正確設置轉換動畫

[英]How to correctly animate transformations on an priorly transformed UIView

問題摘要

無法在已翻譯的UIView上正確執行縮放動畫。

當視圖尚未事先移動時,為了獲得所需的結果,我先應用比例尺,然后再應用平移 我使用UIViewPropertyAnimator動畫化了轉換后的UIViewPropertyAnimator :視圖在相應移動的同時向上或向下縮放。

但是,如果在應用此動畫變換之前已將視圖從其原始位置移動(平移),則我無法獲得將視圖從其新位置移動時放大或縮小的結果。

¡ 盡管變換問題已得到充分記錄-並且在提交問題之前我已經進行了盡職調查-到目前為止,我仍未找到成功的解決方案

轉換動畫代碼

為了便於理解和解決問題,已簡化了代碼。

extension UIView {

   func zoomAndMove(vector: CGPoint, scale: CGPoint){
      self.transform = self.transform.concatenating(CGAffineTransform(scaleX: scale.x, y: scale.y).concatenating(CGAffineTransform(translationX: vector.x, y: vector.y))
   }


   func animateZoomAndMove(from origin: CGPoint, for duration: TimeInterval, cameraZoom: CGPoint, timingFunction: UITimingCurveProvider, controlPoint2: CGPoint(x: 0.8, y: 0.7)) autoplay: Bool = false) -> UIViewPropertyAnimator {
      let animator = UIViewPropertyAnimator(duration: duration, timingParameters: timingFunction)
      let vector = CGPoint(x: self.frame.midX - origin.x, y: self.frame.midY - origin.y)

      animator.addAnimations {
         self.zoomAndMove(vector: vector, scale: cameraZoom)
      }

      if autoplay { animator.startAnimation()}
      return animator
   }
}

到目前為止的嘗試

我試圖修改我的代碼以返回一個轉換,該轉換考慮了zoomAndMove發生之前的先前轉換:

extension UIView {

   func zoomAndMove(vector: CGPoint, scale: CGPoint){

      if self.transform == CGAffineTransform.identity {
          self.transform = self.transform.concatenating(CGAffineTransform(scaleX: scale.x, y: scale.y).concatenating(CGAffineTransform(translationX: vector.x, y: vector.y)) 
      } else {
          let preTransform = self.transform
          self.transform = CGAffineTransform(a: scale.x, b: 0, c: 0, d: scale.y, tx: vector.x + preTransform.tx, ty: vector.y + preTransform.ty)
      }
   }

這段代碼無法達到預期的效果 :視圖跳到一個新位置,正確縮放並“隨機”移動。

我肯定錯過了一些東西-我可能瞄准的是錯誤的最終結果矩陣-但總的來說,我目前仍處於困境。

如果有人對如何執行這樣的簡單任務(例如從已翻譯的UIView縮放和移動UIView)有所了解,我將不勝感激!

最好,


編輯

一幅圖片可能值一千個單詞,所以當我嘗試實現到目前為止提出的各種建議(特別是.scaledBy(:)方法)時,會發生以下情況:

在此處輸入圖片說明

您會注意到最終的轉換是正確的,但動畫卻不正確。

您是否嘗試過將當前轉換分配給屬性,然后修改此復制的屬性,然后重新分配給視圖? 就像是:

let originalTransform = view.transform
let scaledTransform = originalTransform.scaledBy(x: 0.2, y: 0.2)
view.transform = scaledTransform

我使用這種方法創建了一個按鈕動畫,效果很好,但是我不確定這不是您想要的。

首先,感謝@gmogames抽出寶貴的時間提出建議。 交流思想總是有幫助的!!!

實際上,該問題與在應用新轉換之前重置視圖的anchorPoint(或中心)有關,以便動畫正確運行。 因此,使用移動后縮放視圖的簡單得多的示例,這是新方法的外觀:

extension UIView {
    func scaleView(scaleFactor: CGPoint, duration: TimeInterval) {
        // store the view original center
        let oCenter = self.center

        // get the current transformation
        let cTransform = self.transform

        // set the new center of the view 
        self.center = CGPoint(x: self.frame.midX, y: self.frame.midY)

        // clears the transform matrix from potential prior translation
        // Note that you need to take into account potential prior scale of the view into the translation vector!!
        self.transform = self.transform.translatedBy(x: -cTransform.tx / cTransform.a, y: -cTransform.ty / cTransform.d)


        // Animates the transformation
        let animator = UIViewPropertyAnimator(duration: duration, timingParameters: UICubicTimingParameters(controlPoint1: CGPoint(x: 0, y: 0), controlPoint2: CGPoint(x: 1, y: 1))
        animator.addAnimations {
            self.transform = self.transform.scaledBy(x: scaleFactor.x, y: scaleFactor.y)
        }
        // resets the View to its original center and apply the transformation so that the view stays in the right end position
        animator.addCompletion { (position) in
            if position == UIViewAnimatingPosition.end {
                self.center = oCenter
                self.transform = cTransform.scaledBy(x: scaleFactor.x, y: scaleFactor.y)
            }
        }
        animator.startAnimation()
    }
}

這是動畫的結果: 移動+縮放+縮放+恢復原始

在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM