围绕点旋转很简单:One step affine transform for rotation around a point?
但是,我遇到了一个问题:以前旋转“轨道物体”时,它不起作用。这是代码:
import UIKit
class ViewController: UIViewController {
var orbitingImageView: UIImageView!
var centerImageView: UIImageView!
let rr: CGFloat = .pi / 4
override func viewDidLoad() {
super.viewDidLoad()
centerImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 150, height: 150))
centerImageView.center = CGPoint(x: 300, y: 400)
centerImageView.backgroundColor = .red
view.addSubview(centerImageView)
orbitingImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
orbitingImageView.center = CGPoint(x: 500, y: 400)
orbitingImageView.backgroundColor = .blue
view.addSubview(orbitingImageView)
orbitingImageView.transform = orbitingImageView.transform
.rotated(by: rr) //without it works fine
n()
}
func n() {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) { //little trick to make an animation
let angle: CGFloat = 0.05
let orb = self.orbitingImageView!
let cen = self.centerImageView!
let a = CGPoint(x: cen.center.x - orb.center.x,
y: cen.center.y - orb.center.y)
self.orbitingImageView.transform = self.orbitingImageView.transform
.translatedBy(x: a.x, y: a.y)
.rotated(by: angle)
.translatedBy(x: -a.x, y: -a.y)
self.n()
}
}
}
extension CGAffineTransform { //helper methods
func getScale() -> CGFloat {
return (self.a * self.a + self.c * self.c).squareRoot()
}
func getRotation() -> CGFloat {
return atan2(self.b, self.a)
}
}
现在,我可以像这样修改n()函数:
func n() {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) { //little trick to make an animation
let angle: CGFloat = 0.05
let orb = self.orbitingImageView!
let cen = self.centerImageView!
let a = CGPoint(x: cen.center.x - orb.center.x,
y: cen.center.y - orb.center.y)
self.orbitingImageView.transform = self.orbitingImageView.transform
.rotated(by: -self.rr)
.translatedBy(x: a.x, y: a.y)
.rotated(by: angle)
.translatedBy(x: -a.x, y: -a.y)
.rotated(by: self.rr)
self.n()
}
}
它再次起作用。但是,此方法需要存储初始角度(变量rr)。
如何计算rr?
这只是我在“真实”项目中使用的简化代码。在那里,我可以平移/收缩/旋转屏幕上的多个对象。例如,如果我选择了2个对象,则第一个对象(用手指在其上)应以其中心旋转,而第二个对象应以第一个点的中心为中心旋转。然后就是这个问题,因为如果第二个对象在单独旋转之前(通过它的中心)旋转了,我就需要旋转(这里是rr)。
答案 0 :(得分:0)
最后,我找到了解决方案。我没有用计算rr的方法,而是用1步方法代替了围绕点的3步旋转:
let tr = CGAffineTransform(
a: cos(angle),
b: sin(angle),
c: -sin(angle),
d: cos(angle),
tx: a.x - a.x * cos(angle) + a.y * sin(angle),
ty: a.y - a.x * sin(angle) - a.y * cos(angle)
)
self.orbitingImageView.transform = self.orbitingImageView.transform
.concatenating(tr)
整个代码:
import UIKit
class ViewController: UIViewController {
var orbitingImageView: UIImageView!
var centerImageView: UIImageView!
let rr: CGFloat = .pi / 4
override func viewDidLoad() {
super.viewDidLoad()
centerImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 150, height: 150))
centerImageView.center = CGPoint(x: 300, y: 400)
centerImageView.backgroundColor = .red
view.addSubview(centerImageView)
orbitingImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
orbitingImageView.center = CGPoint(x: 500, y: 400)
orbitingImageView.backgroundColor = .blue
view.addSubview(orbitingImageView)
orbitingImageView.transform = orbitingImageView.transform
.rotated(by: rr)
.scaledBy(x: 0.5, y: 0.5) //even works with prescaling
n()
}
func n() {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
let angle: CGFloat = 0.05
let orb = self.orbitingImageView!
let cen = self.centerImageView!
let a = CGPoint(x: cen.center.x - orb.center.x,
y: cen.center.y - orb.center.y)
let tr = CGAffineTransform(
a: cos(angle),
b: sin(angle),
c: -sin(angle),
d: cos(angle),
tx: a.x - a.x * cos(angle) + a.y * sin(angle),
ty: a.y - a.x * sin(angle) - a.y * cos(angle)
)
self.orbitingImageView.transform = self.orbitingImageView.transform
.concatenating(tr)
self.n()
}
}
}
现在,它既可以进行预旋转,也可以进行预缩放。