Swift CGAffineTransform 旋转跳跃

Swift CGAffineTransform rotation jumps

我在自己的项目中使用了 How to rotate an UIImageView using TouchesMoved 中的信息。但是我发现了一个问题,我想不出如何解决它。

原post中的视图也有同样的问题,但小视图几乎不明显。 A做了这个示例代码。查看视图如何“跳跃”。触摸点始终位于锚点的左侧。我怎样才能避免这种跳跃。

class ViewController: UIViewController {
    var myView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        myView = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 200))
        myView.center = self.view.center
        myView.isUserInteractionEnabled = true
        myView.backgroundColor = UIColor.red
        self.view.addSubview(myView)
        myView.layer.anchorPoint = CGPoint(x: 0.5, y: 0.0)

    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch: UITouch = touches.first!

        if touch.view === myView {
            let position = touch.location(in: self.view)
            let target = myView.center
            let angle = atan2(target.y-position.y, target.x-position.x)
            myView.transform = CGAffineTransform(rotationAngle: angle)
        }
    }
}

看来你的问题在行

let angle = atan2(target.y-position.y, target.x-position.x)

atan2 returns0到π之间的一个数,而不是你想要的,-π到π之间的一个数。您应该能够通过将 (target.y - position.y) 与 0 进行比较来修复它。当它大于零时,您的原始返回值应该是好的。当它小于零时,你会想要减去 π 以获得正确的角度。

你有两个主要问题:

  • 您没有考虑原始触摸的位置。您需要在 touchesBegan 中记录该信息并计算出相对于该信息的旋转变换角度。

  • 你说 let target = myView.center 好像这是我们旋转的点。但它不是,因为你移动了 myViewanchorPoint

这是工作代码(取自我的书),可让您拖动以围绕其自身中心旋转 myView

class ViewController: UIViewController {
    var myView: UIView!
    override func viewDidLoad() {
        super.viewDidLoad()
        myView = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 200))
        myView.center = self.view.center
        myView.isUserInteractionEnabled = true
        myView.backgroundColor = UIColor.red
        self.view.addSubview(myView)
    }
    func pToA (_ t:UITouch) -> CGFloat {
        let loc = t.location(in: myView)
        let c = myView.convert(myView.center, from:myView.superview!)
        return atan2(loc.y - c.y, loc.x - c.x)
    }
    var initialAngle = CGFloat(0)
    var angle = CGFloat(0)
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.initialAngle = pToA(touches.first!)
    }
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        let ang = pToA(touches.first!) - self.initialAngle
        let absoluteAngle = self.angle + ang
        myView.transform = myView.transform.rotated(by: ang)
        self.angle = absoluteAngle
    }
}

但是如果您真的想围绕不同的点旋转(像您的代码那样移动锚点),则需要相应地调整该代码。