如何动画缩放和移动 UILabel,然后在完成后将其变换设置回身份并保留其框架?

How to animate scaling and moving a UILabel, then set its transform back to the identity when finished and preserve its frame?

我有一个 UILabel 正在尝试缩放和平移,我想制作动画。我通过在 UIView.animate 块中设置它的 transform 来做到这一点。动画完成后,我想将视图的 transform 设置回 .identity 并更新其框架,使其保持在 CGAffineTransform 移动它的位置。伪代码:

func animateMovement(label: UILabel,
                     newWidth: CGFloat,
                     newHeight: CGFloat,
                     newOriginX: CGFloat,
                     newOriginY: CGFloat)
{        
    UIView.animate(withDuration: duration, animations: {
        label.transform = ??? // Something that moves it to the new location and new size
    }) {
        label.frame = ??? // The final frame from the above animation
        label.transform = CGAffineTransform.identity
    }
}

至于为什么我不简单地在动画块中分配新帧:我在标签内有文本,我想随动画缩放,这在动画更改帧而不是变换时是不可能的.

我遇到了坐标 space 问题,我可以看出这是因为在动画之后它不在正确的位置(标签的原点错误)。

这是我想出的答案。这将在动画持续时间内缩放内容,然后在完成时重置对象以进行恒等变换。

static func changeFrame(label: UILabel,
                        toOriginX newOriginX: CGFloat,
                        toOriginY newOriginY: CGFloat,
                        toWidth newWidth: CGFloat,
                        toHeight newHeight: CGFloat,
                        duration: TimeInterval)
{
    let oldFrame = label.frame
    let newFrame = CGRect(x: newOriginX, y: newOriginY, width: newWidth, height: newHeight)

    let translation = CGAffineTransform(translationX: newFrame.midX - oldFrame.midX,
                                        y: newFrame.midY - oldFrame.midY)
    let scaling = CGAffineTransform(scaleX: newFrame.width / oldFrame.width,
                                    y: newFrame.height / oldFrame.height)

    let transform = scaling.concatenating(translation)

    UIView.animate(withDuration: duration, animations: {
        label.transform = transform
    }) { _ in
        label.transform = .identity
        label.frame = newFrame
    }
}