CGAffineTransform:同时应用平移和缩放
CGAffineTransform: Apply translate and scale at the same time
我有两个 UILabel
。屏幕左侧较大,右侧较小。
我正在尝试使用 CGAffineTransform
制作动画,将较小的标签移动到较大的标签的位置并将其缩放到相同的大小,然后将较大的标签移出屏幕。
我实际上并没有移动标签,在动画完成后,我更改了标签上的文本 属性 并将它们的变换设置为 identity
。
我的问题是我不知道如何计算我必须翻译我的小标签的确切 x 和 y 值。我认为我的值不准确,因为我在翻译标签的同时缩放了标签,并且 tx
和 ty
值是使用较小标签的非缩放尺寸计算的。
我目前在做什么:
tx
:大标签的宽度+它与小标签的距离,ty
:两个标签中心在y轴上的距离
有多种方法可以做到这一点 - 这是一个...
首先计算平移值和比例值,然后将它们连接起来:
let translation = CGAffineTransform(translationX: xMove, y: yMove)
let scaling = CGAffineTransform(scaleX: xScale, y: yScale)
let fullTransform = scaling.concatenating(translation)
这是一个完整的示例...我们添加了两个具有不同字体大小、位置和背景颜色的标签(以便于查看)。点击任意位置 运行 变换动画:
class ViewController: UIViewController {
let labelA = UILabel()
let labelB = UILabel()
var aTop: NSLayoutConstraint!
var aLeading: NSLayoutConstraint!
var bTop: NSLayoutConstraint!
var bLeading: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
[labelA, labelB].forEach { v in
v.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(v)
}
labelA.text = "Label A"
labelB.text = "Label B"
labelA.backgroundColor = .green
labelB.backgroundColor = .cyan
labelA.font = .systemFont(ofSize: 40.0)
labelB.font = .systemFont(ofSize: 20.0)
// respect safe area
let g = view.safeAreaLayoutGuide
aTop = labelA.topAnchor.constraint(equalTo: g.topAnchor, constant: 100.0)
aLeading = labelA.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 40.0)
bTop = labelB.topAnchor.constraint(equalTo: g.topAnchor, constant: 300.0)
bLeading = labelB.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 240.0)
NSLayoutConstraint.activate([
aTop, aLeading,
bTop, bLeading,
])
let t = UITapGestureRecognizer(target: self, action: #selector(self.doAnim(_:)))
view.addGestureRecognizer(t)
}
@objc func doAnim(_ g: UITapGestureRecognizer?) -> Void {
let targetPoint = labelA.center
let originPoint = labelB.center
let xMove = targetPoint.x - originPoint.x
let yMove = targetPoint.y - originPoint.y
let xScale = labelA.frame.width / labelB.frame.width
let yScale = labelA.frame.height / labelB.frame.height
let translation = CGAffineTransform(translationX: xMove, y: yMove)
let scaling = CGAffineTransform(scaleX: xScale, y: yScale)
let fullTransform = scaling.concatenating(translation)
UIView.animate(withDuration: 1.0, animations: {
self.labelB.transform = fullTransform
}) { [weak self] b in
guard let self = self else { return }
self.labelB.transform = .identity
self.labelB.font = self.labelA.font
self.bTop.constant = self.aTop.constant
self.bLeading.constant = self.aLeading.constant
}
}
}
我有两个 UILabel
。屏幕左侧较大,右侧较小。
我正在尝试使用 CGAffineTransform
制作动画,将较小的标签移动到较大的标签的位置并将其缩放到相同的大小,然后将较大的标签移出屏幕。
我实际上并没有移动标签,在动画完成后,我更改了标签上的文本 属性 并将它们的变换设置为 identity
。
我的问题是我不知道如何计算我必须翻译我的小标签的确切 x 和 y 值。我认为我的值不准确,因为我在翻译标签的同时缩放了标签,并且 tx
和 ty
值是使用较小标签的非缩放尺寸计算的。
我目前在做什么:
tx
:大标签的宽度+它与小标签的距离,ty
:两个标签中心在y轴上的距离
有多种方法可以做到这一点 - 这是一个...
首先计算平移值和比例值,然后将它们连接起来:
let translation = CGAffineTransform(translationX: xMove, y: yMove)
let scaling = CGAffineTransform(scaleX: xScale, y: yScale)
let fullTransform = scaling.concatenating(translation)
这是一个完整的示例...我们添加了两个具有不同字体大小、位置和背景颜色的标签(以便于查看)。点击任意位置 运行 变换动画:
class ViewController: UIViewController {
let labelA = UILabel()
let labelB = UILabel()
var aTop: NSLayoutConstraint!
var aLeading: NSLayoutConstraint!
var bTop: NSLayoutConstraint!
var bLeading: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
[labelA, labelB].forEach { v in
v.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(v)
}
labelA.text = "Label A"
labelB.text = "Label B"
labelA.backgroundColor = .green
labelB.backgroundColor = .cyan
labelA.font = .systemFont(ofSize: 40.0)
labelB.font = .systemFont(ofSize: 20.0)
// respect safe area
let g = view.safeAreaLayoutGuide
aTop = labelA.topAnchor.constraint(equalTo: g.topAnchor, constant: 100.0)
aLeading = labelA.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 40.0)
bTop = labelB.topAnchor.constraint(equalTo: g.topAnchor, constant: 300.0)
bLeading = labelB.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 240.0)
NSLayoutConstraint.activate([
aTop, aLeading,
bTop, bLeading,
])
let t = UITapGestureRecognizer(target: self, action: #selector(self.doAnim(_:)))
view.addGestureRecognizer(t)
}
@objc func doAnim(_ g: UITapGestureRecognizer?) -> Void {
let targetPoint = labelA.center
let originPoint = labelB.center
let xMove = targetPoint.x - originPoint.x
let yMove = targetPoint.y - originPoint.y
let xScale = labelA.frame.width / labelB.frame.width
let yScale = labelA.frame.height / labelB.frame.height
let translation = CGAffineTransform(translationX: xMove, y: yMove)
let scaling = CGAffineTransform(scaleX: xScale, y: yScale)
let fullTransform = scaling.concatenating(translation)
UIView.animate(withDuration: 1.0, animations: {
self.labelB.transform = fullTransform
}) { [weak self] b in
guard let self = self else { return }
self.labelB.transform = .identity
self.labelB.font = self.labelA.font
self.bTop.constant = self.aTop.constant
self.bLeading.constant = self.aLeading.constant
}
}
}