【问题标题】:Rotate object around point when it's initially rotated by it's center最初按中心旋转时围绕点旋转对象
【发布时间】:2018-11-05 15:01:33
【问题描述】:

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

【问题讨论】:

    标签: ios swift


    【解决方案1】:

    最后,我找到了解决方案。我没有计算 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()
            }
        }
    
    }
    

    现在它适用于预旋转和预缩放。

    【讨论】:

      猜你喜欢
      • 2021-06-06
      • 2021-09-13
      • 2016-09-10
      • 1970-01-01
      • 2013-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多