iOS Swift: 在不调整大小的情况下旋转和缩放 UIView

iOS Swift: Rotate and Scale UIView without resizing

我有一个 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
        }
    }

}

缩放前

缩放后

旋转后

我希望它在不影响视图大小的情况下旋转。我怎样才能做到这一点?

您在应用旋转变换时正在重置视图的缩放变换。创建一个 属性 来保存视图的原始比例。

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

我用这个answer作为提取比例值的参考

我遇到了同样的问题一旦我用手指捏住,然后在我从一个按钮旋转后它会自动从当前按比例缩小但我在下面设置了逻辑。

 @objc func rotateViewPanGesture(_ recognizer: UIPanGestureRecognizer) {
            touchLocation = recognizer.location(in: superview)
            let center = CGRectGetCenter(frame)

            switch recognizer.state {
            case .began:
                deltaAngle = atan2(touchLocation!.y - center.y, touchLocation!.x - center.x) - CGAffineTrasformGetAngle(transform)
                initialBounds = bounds
                initialDistance = CGpointGetDistance(center, point2: touchLocation!)

            case .changed:

                let ang = atan2(touchLocation!.y - center.y, touchLocation!.x - center.x)
                let angleDiff = deltaAngle! - ang

                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)

                let currentScale = CGPoint(x: sx, y: sy)
                let scale = CGAffineTransform(scaleX: currentScale.x, y: currentScale.y)
                self.transform = scale.rotated(by: -angleDiff)

                layoutIfNeeded()
            case .ended:

              print("end gesture status")
            default:break

            }
        }