繁体   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