当对象最初由中心旋转时,围绕对象旋转

时间:2018-11-05 15:01:34

标签: ios swift

围绕点旋转很简单: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)。

1 个答案:

答案 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()
        }
    }

}

现在,它既可以进行预旋转,也可以进行预缩放。