链接 UIView 动画与 CGAffineTransformscale 和翻译

Chaining UIView animation with CGAffineTransform scale & translate

我正在尝试使用 animate(withDuration:animations:) 为 Playground 中的 UIView 设置动画。目标是将视图向下移动,然后向右移动,同时按比例放大。

所以我分两步进行,在第一个动画完成后调用第二个动画。

这是我要应用到我的视图的 3 个转换

let scaleUp = CGAffineTransform(scaleX: 2, y: 2)
let moveDown = CGAffineTransform(translationX: 0, y: 100)
let moveRight = CGAffineTransform(translationX: 100, y: 0)

要做 moveDown 然后 moveRight 我将第二个连接到第一个。

UIView.animate(withDuration: 2, animations: {
            circleView.transform = moveDown
        }) { _ in
            //First animation completed
            UIView.animate(withDuration: 4, animations: {
                circleView.transform = moveDown.concatenating(moveRight)
            })
        }

`


现在,当我试图在向右移动的同时放大视图时,它似乎正在将比例应用于已经转换的视图,这导致在第二个动画开始之前将所有内容向下移动(2 次)。

UIView.animate(withDuration: 2, animations: {
            circleView.transform = moveDown
        }) { _ in
            //First animation completed
            UIView.animate(withDuration: 2, animations: {
                circleView.transform = moveDown.concatenating(scaleUp.concatenating(moveRight))
            })
        }

如何在不重置初始转换的情况下实现右移+放大?

在应用它们的变换顺序中,我认为是因为您在平移之前应用缩放,它采用按比例放大的值。

moveRight.concatenating(scaleUp)

可能工作正常。

我认为您的问题已经得到解答 in this post。据说,为了实现您的目标(两个同步动画),您需要使用 CAAnimationand 和 layer addAnimation

我试过了,效果很好

let scaleAA = CABasicAnimation(keyPath: "transform.scale")
scaleAA.fromValue = 1
scaleAA.byValue = 2
scaleAA.duration = 1
scaleAA.timingFunction = CAMediaTimingFunction.init(name: .easeOut)

let scaleXX = CABasicAnimation(keyPath: "position.x")
scaleXX.fromValue = 0
scaleXX.byValue = 20
scaleXX.duration = 1
scaleXX.timingFunction = CAMediaTimingFunction.init(name: .easeOut)

UIView.animate(withDuration: 1, animations: {
    v1.transform = moveDown
}) { _ in
    //First animation completed
    v1.layer.add(scaleAA, forKey: "scale")
    v1.layer.add(scaleXX, forKey: "xxxx")
}

我的解决方案更像是一个热修复程序,但它正是您想要的:

1执行下移动画

2 恢复上面的转换(没有动画)

3circleView 设置为下移变换后的位置(无动画)

4 执行向右移动和放大的动画

UIView.animate(withDuration: 2, animations: {
        circleView.transform = moveDown //1
    }) { _ in
        //First animation completed
        circleView.transform = .identity //2
        circleView.frame.origin.y += 100 //3
        UIView.animate(withDuration: 2, animations: {
            circleView.transform = moveRight.concatenating(scaleUp) //4
        })
    }