【问题标题】:iOS Swift: Rotate and Scale UIView without resizingiOS Swift:无需调整大小即可旋转和缩放 UIView
【发布时间】:2019-01-04 15:21:25
【问题描述】:

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

}

缩放前

缩放后

旋转后

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

【问题讨论】:

    标签: ios swift uiview cgaffinetransform


    【解决方案1】:

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

    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作为提取比例值的参考。

    【讨论】:

    • 它可以工作,但为什么它不能通过let newRotation = sender.rotation + originalRotation self.transform = self.transform.rotated(by: newRotation) 工作??
    • @AbhishekThapliyal 如果您不重置视图转换,那应该确实有效。
    • 你能帮帮我吗,检查第一个答案中的 cmets ??? stackoverflow.com/questions/62372147/…
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-30
      • 2015-12-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多