iOS Swift: вращение и масштабирование UIView без изменения размера - PullRequest
0 голосов
/ 04 января 2019

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

extension UIView {

    func addPinchGesture() {
        var pinchGesture = UIPinchGestureRecognizer()
        pinchGesture = UIPinchGestureRecognizer(target: self,
                                                action: #selector(handlePinchGesture(_:)))
        self.addGestureRecognizer(pinchGesture)
    }

    @objc func handlePinchGesture(_ sender: UIPinchGestureRecognizer) {
        self.transform = self.transform.scaledBy(x: sender.scale, y: sender.scale)
        sender.scale = 1
    }

}

// ROTATION
extension UIView {

    func addRotationGesture() {
        var rotationGesture = RotationGestureRecognizer()
        rotationGesture = RotationGestureRecognizer(target: self,
                                                    action: #selector(handleRotationGesture(_:)))
        self.addGestureRecognizer(rotationGesture)
    }

    @objc func handleRotationGesture(_ sender: RotationGestureRecognizer) {
        var originalRotation = CGFloat()
        switch sender.state {
        case .began:
            sender.rotation = sender.lastRotation
            originalRotation = sender.rotation
        case .changed:
            let newRotation = sender.rotation + originalRotation
            self.transform = CGAffineTransform(rotationAngle: newRotation) // Rotation is fine but it is resizing view
//            self.transform = self.transform.rotated(by: newRotation / CGFloat(180 * Double.pi)) // NOT WORKING i.e. irregular rotation
        case .ended:
            sender.lastRotation = sender.rotation
        default:
            break
        }
    }

}

Перед масштабированием

enter image description here

после масштабирования

enter image description here

после вращения

enter image description here

Я хочу, чтобы он вращался, не влияя на размер вида. Как мне этого добиться?

1 Ответ

0 голосов
/ 04 января 2019

Вы сбрасываете масштабное преобразование вида при применении вращения вращения. Создайте свойство для хранения исходного масштаба представления.

var currentScale: CGFloat = 0

И когда пинч будет сделан, сохраните значение currentScale в текущем масштабе. Затем при вращении также используйте эту шкалу, прежде чем применять вращение.

let scaleTransform = CGAffineTransform(scaleX: currentScale, y: currentScale)

let concatenatedTransform = scaleTransform.rotated(by: newRotation)
self.transform = concatenatedTransform

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

extension UIView {

    var currentScale: CGPoint {
        let a = transform.a
        let b = transform.b
        let c = transform.c
        let d = transform.d

        let sx = sqrt(a * a + b * b)
        let sy = sqrt(c * c + d * d)

        return CGPoint(x: sx, y: sy)
    }


    func addPinchGesture() {
        var pinchGesture = UIPinchGestureRecognizer()
        pinchGesture = UIPinchGestureRecognizer(target: self,
                                                action: #selector(handlePinchGesture(_:)))
        self.addGestureRecognizer(pinchGesture)
    }

    @objc func handlePinchGesture(_ sender: UIPinchGestureRecognizer) {
        self.transform = self.transform.scaledBy(x: sender.scale, y: sender.scale)
        sender.scale = 1
    }

}

// ROTATION
extension UIView {

    func addRotationGesture() {
        var rotationGesture = RotationGestureRecognizer()
        rotationGesture = RotationGestureRecognizer(target: self,
                                                    action: #selector(handleRotationGesture(_:)))
        self.addGestureRecognizer(rotationGesture)
    }

    @objc func handleRotationGesture(_ sender: RotationGestureRecognizer) {
        var originalRotation = CGFloat()
        switch sender.state {
        case .began:
            sender.rotation = sender.lastRotation
            originalRotation = sender.rotation
        case .changed:
            let scale = CGAffineTransform(scaleX: currentScale.x, y: currentScale.y)
            let newRotation = sender.rotation + originalRotation

            self.transform = scale.rotated(by: newRotation)
        case .ended:
            sender.lastRotation = sender.rotation
        default:
            break
        }
    }
}

Я использовал этот ответ как ссылку для извлечения значения шкалы.

...