Rotating around point is simple: One step affine transform for rotation around a point?
However, I've encountered a problem: it doesn't work when "orbiting object" is rotated before. Here's the code:
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)
}
}
Now, I can modify n() function like this:
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()
}
}
And it works again. However, this method requires to store initial angle (variable rr).
How can I calculate rr?
This is just a simplified version of code which I use it in the "real" project. There I can pan/pinch/rotate multiple objects on the screen. If, for example, I've selected 2 objects the first object (on which I have my finger) should rotate by its center while the second one should rotate around center of the first point. And then it's this problem, because if second object was rotated before alone (by it's center) I need this rotation (which is rr here).