Swift CGAffineTransform скачки вращения - PullRequest
0 голосов
/ 24 декабря 2018

Я использовал информацию из Как повернуть UIImageView с помощью TouchesMoved в моем собственном проекте.Но я нашел проблему и не могу понять, как ее решить.

У представления в оригинальном посте та же проблема, но с небольшим представлением это почти не заметно.А сделал этот пример кода.Посмотрите, как вид «прыгает».Точка касания всегда остается от точки привязки.Как я могу избежать этого прыжка.

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)
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 24 декабря 2018

У вас есть две основные проблемы:

  • Вы не принимаете во внимание, где был первоначальный штрих.Вам нужно записать эту информацию в touchesBegan и определить угол вашего поворота относительно нее.

  • Вы говорите let target = myView.center, как если бы это была точка, которой мы являемсявращается вокруг.Но это не так, потому что вы переместили anchorPoint из myView.

Вот рабочий код (взят из моей книги), который позволяет перетаскивать 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
    }
}

Но если вы действительно хотитевращайте вокруг другой точки (перемещая опорную точку, как это делает ваш код), вам необходимо соответствующим образом изменить этот код.

0 голосов
/ 24 декабря 2018

Похоже, ваша проблема в строке

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

atan2 возвращает число от 0 до π, а не то, что вы хотите, число от -π до π.Вы должны быть в состоянии исправить это, сравнив (target.y - position.y) с 0. Когда оно больше нуля, ваше исходное возвращаемое значение должно быть хорошим.Когда оно меньше нуля, вам нужно вычесть π, чтобы получить правильный угол.

...