Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift 3: How do I pinch to scale and rotate UIImageView?

I am really struggling to find tutorials online as well as already answered questions (I have tried them and they don't seem to work). I have a UIImageView that I have in the centre of my view. I am currently able to tap and drag this wherever I want on screen. I want to be able to pinch to scale and rotate this view. How do I achieve this? I have tried the code for rotation below but it doesn't seem to work? Any help will be a massive help and marked as answer. Thank you guys.

    import UIKit

class DraggableImage: UIImageView {

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

        self.backgroundColor = .blue

    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {

        self.backgroundColor = .green

    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let touch = touches.first {
            let position = touch.location(in: superview)
            center = CGPoint(x: position.x, y: position.y)
        }
    }

}

class CVController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        let rotateGesture = UIRotationGestureRecognizer(target: self, action: #selector(rotateAction(sender:)))
        firstImageView.addGestureRecognizer(rotateGesture)

        setupViews()
    }

    func rotateAction(sender: UIRotationGestureRecognizer) {
        let rotatePoint = sender.location(in: view)
        let firstImageView = view.hitTest(rotatePoint, with: nil)
        firstImageView?.transform = (firstImageView?.transform.rotated(by: sender.rotation))!
        sender.rotation = 0
    }

    let firstImageView: DraggableImage = {
        let iv = DraggableImage()
        iv.backgroundColor = .red
        iv.isUserInteractionEnabled = true
        return iv
    }()

    func setupViews() {
        view.addSubview(firstImageView)

        let firstImageWidth: CGFloat = 50
        let firstImageHeight: CGFloat = 50

        firstImageView.frame = CGRect(x: (view.frame.width / 2) - firstImageWidth / 2, y: (view.frame.height / 2) - firstImageWidth / 2, width: firstImageWidth, height: firstImageHeight)
    }

}
like image 843
Jimmy Avatar asked Mar 23 '17 00:03

Jimmy


People also ask

How to rotate image in image view by an angle in iOS?

So, In this post, we will be seeing how to rotate the image in an image view by an angle in an iOS application. Step 1 − Open Xcode→SingleViewApplication→name it RotateImage. Step 2 − Open Main.storyboard, add UIImageView and add 2 buttons as shown below name them ROTATE BY 90 DEGREES AND ROTATE BY 45 DEGREES.

What is the difference between UIImageView and UIScrollView?

Swift - UIImageView zooms bigger than UIScrollView 0 Swift pinch to zoom 0 How do I make an image act like a map (zoom/pan/map markers)?

How to handle movement on a zoomed image with a UIScrollView?

How to correctly handle movement on a zoomed image with a UIScrollView? 1 Zoom & Pin on the same UIImageView 0 Zoom into UIView without pixelating 0 Swift pinch zoom image quality

What is the zoom scale of ScrollView when pinching?

2 When pinching ends, call scrollView.zoomScale = 1.0 – Marco Leong Aug 22 '18 at 0:09 Working Solution, Thanks – Naveed Ahmad May 13 '19 at 12:33 Add a comment | 12 You can use ImageScrollView open source, a zoomable and scrollable image view.


1 Answers

You have a some problems in your code. First you need to add the UIGestureRecognizerDelegate to your view controller and make it your gesture recognizer delegate. You need also to implement shouldRecognizeSimultaneously method and return true. Second when applying the scale you need to save the transform when the pinch begins and apply the scale in top of it:

class DraggableImageView: UIImageView {
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        backgroundColor = .blue
    }
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        backgroundColor = .green
    }
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let position = touches.first?.location(in: superview){
            center = position
        }
    }
}

class ViewController: UIViewController, UIGestureRecognizerDelegate {
    
    var identity = CGAffineTransform.identity
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        setupViews()
        
        let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(scale))
        let rotationGesture = UIRotationGestureRecognizer(target: self, action: #selector(rotate))
        
        pinchGesture.delegate = self
        rotationGesture.delegate = self

        view.addGestureRecognizer(pinchGesture)
        view.addGestureRecognizer(rotationGesture)
    }
    let firstImageView: DraggableImageView = {
        let iv = DraggableImageView()
        iv.backgroundColor = .red
        iv.isUserInteractionEnabled = true
        return iv
    }()
    
    func setupViews() {
        view.addSubview(firstImageView)
        let firstImageWidth: CGFloat = 50
        let firstImageHeight: CGFloat = 50
        firstImageView.frame = CGRect(x: view.frame.midX - firstImageWidth / 2, y: view.frame.midY - firstImageWidth / 2, width: firstImageWidth, height: firstImageHeight)
    }
    @objc func scale(_ gesture: UIPinchGestureRecognizer) {
        switch gesture.state {
        case .began:
            identity = firstImageView.transform
        case .changed,.ended:
            firstImageView.transform = identity.scaledBy(x: gesture.scale, y: gesture.scale)
        case .cancelled:
            break
        default:
            break
        }
    }
    @objc func rotate(_ gesture: UIRotationGestureRecognizer) {
        firstImageView.transform = firstImageView.transform.rotated(by: gesture.rotation)
    }
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}
like image 181
Leo Dabus Avatar answered Oct 21 '22 03:10

Leo Dabus