应用了平移变换,但只添加了缩放变换

Translate transformation applied while only scale transformation added

我正在创建一个动画,我想在应用在线检索一些数据时使用它。我的想法是我有一些连续的点,它们将被缩放到比它们的原始大小更小然后 return 到它们的原始大小并且所有这些在每次缩放之间都有一个小的延迟。动画重复并使用自动反转模式。

为此,我使用核心图形方法创建了一些点,将它们添加到视图中并使用 CGAffineTransformMakeTranslation 转换定位它们。然后我使用一个循环来延迟地对它们进行动画处理,并使用 CGAffineTransformScale 转换进行缩放。

问题:我没有得到预期的动画(至少是我所期待的)。当点被缩放时,它们也会移回原来的位置。

谁能告诉我为什么在 UIView 动画中有平移变换,我只指定了缩放比例?

代码如下:

private var dots = [UIImage]()

public init(numberOfDots: Int, hexaColor: Int, dotDiameter: CGFloat = 30, animationDuration: NSTimeInterval = 1) {
    self.dotDiameter = dotDiameter
    self.animationDuration = animationDuration

    for _ in 0 ..< numberOfDots {
        dots.append(GraphicHelper.drawDisk(hexaColor, rectForDisk: CGRect(x: 0, y: 0, width: dotDiameter, height: dotDiameter), withStroke: false))
    }

    let spaceBetweenDisks: CGFloat = dotDiameter / 3
    let viewWidth: CGFloat = CGFloat(numberOfDots) * dotDiameter + CGFloat(numberOfDots - 1) * spaceBetweenDisks
    super.init(frame: CGRectMake(0, 0, viewWidth, dotDiameter))

    setup()
}

private func setup() {
    for (i, dot) in dots.enumerate() {
        let dotImageView = UIImageView(image: dot)

        addSubview(dotImageView)

        let spaceBetweenDisks: CGFloat = dotDiameter / 3
        let xOffset = CGFloat(i) * (dotDiameter + spaceBetweenDisks)

        dotImageView.transform = CGAffineTransformMakeTranslation(xOffset, 0)
    }
}

public func startAnimation() {
    for i in 0 ..< self.dots.count {
        let dotImageView: UIImageView = self.subviews[i] as! UIImageView
        let transformBeforeAnimation = dotImageView.transform

        let delay: NSTimeInterval = NSTimeInterval(i)/NSTimeInterval(self.dots.count) * animationDuration

        UIView.animateWithDuration(animationDuration, delay: delay, options: [UIViewAnimationOptions.Repeat, UIViewAnimationOptions.Autoreverse], animations: {

            dotImageView.transform = CGAffineTransformScale(dotImageView.transform, 0.05, 0.05)

            }, completion: { finished in
                dotImageView.transform = CGAffineTransformIdentity
                dotImageView.transform = transformBeforeAnimation
        })
    }
}

编辑:

我找到了修复程序,但我不明白它是如何修复的。所以如果有人能解释一下。

我添加了这两行:

dotImageView.transform = CGAffineTransformIdentity
dotImageView.transform = transformBeforeAnimation

startAnimation 这一行之前:

dotImageView.transform = CGAffineTransformScale(dotImageView.transform, 0.05, 0.05)

你确定它回到原来的位置而不是根据原来的中心点缩放吗?尝试通过执行以下操作更改应用转换的顺序:

public func startAnimation() {
    for i in 0 ..< self.dots.count {
        let dotImageView: UIImageView = self.subviews[i] as! UIImageView
        let transformBeforeAnimation = dotImageView.transform

        let delay: NSTimeInterval = NSTimeInterval(i)/NSTimeInterval(self.dots.count) * animationDuration

        UIView.animateWithDuration(animationDuration, delay: delay, options: [UIViewAnimationOptions.Repeat, UIViewAnimationOptions.Autoreverse], animations: {
            // make scale transform separately and concat the two
            let scaleTransform = CGAffineTransformMakeScale(0.05, 0.05)
            dotImageView.transform = CGAffineTransformConcat(transformBeforeAnimation, scaleTransform)

            }, completion: { finished in
                dotImageView.transform = CGAffineTransformIdentity
                dotImageView.transform = transformBeforeAnimation
        })
    }
}

来自苹果文档:

Note that matrix operations are not commutative—the order in which you concatenate matrices is important. That is, the result of multiplying matrix t1 by matrix t2 does not necessarily equal the result of multiplying matrix t2 by matrix t1.

因此,请记住,分配一个变换会创建一个新的仿射变换矩阵,并且串联会用新矩阵修改现有矩阵 - 您应用这些矩阵的顺序可能会产生不同的结果。

为了完成这项工作,我还在 dotImageView 上更新了您翻译的价值。它需要是 requiredTranslation / scale.. 如果在比例之前应用翻译。所以在你的 viewDidLoad:

dotImageViewtransform = CGAffineTransformMakeTranslation(1000, 0)

然后是动画:

// make scale transform separately and concat the two
let scaleTransform = CGAffineTransformMakeScale(0.05, 0.05)
self.card.transform = CGAffineTransformConcat(transformBeforeAnimation, scaleTransform)

结合平移和缩放变换令人困惑且难以正确处理。

我不得不花太多时间在方格纸上和深思熟虑才能弄明白,我现在太累了。

不要那样做。通过移动它们的中心坐标来放置您的点图像视图,并将变换保留在标识处。然后当你缩放它们时,它们应该像你想要的那样缩放。

请注意,如果您希望它们同时移动和缩放,您可以在同一个 animateWithDuration 调用中同时更改视图的中心 属性 和它的变换比例,它可以正常工作。 (顺便说一句,改变框架不是这样。如果你改变了变换,那么框架 属性 就不能再正常工作了。Apple 的文档说 reading/writing 的结果是框架 属性 具有非恒等式变换的视图是 "undefined"。)