swift 通过按下ImageView角上的圆圈并拖动它使其变小/变大来调整ImageView的大小

lzfw57am  于 2023-01-25  发布在  Swift
关注(0)|答案(1)|浏览(129)

我一直在做这个包含UIImageView的小应用程序。我可以点击它,图像的每个角上都会出现4个圆圈。我必须能够从角上拖动手指来调整图像的大小。但是调整大小不起作用。根据我的理解-我必须在 * touchesMoved * 方法中更新imageView的约束。
我用这个帖子作为参考:How to resize UIView by dragging from its edges?
设置图像视图、滚动视图和按钮

struct ResizeRect{
        var topTouch = false
        var leftTouch = false
        var rightTouch = false
        var bottomTouch = false
        var middelTouch = false
    }

这是我画在角落里的圆圈

private var topLeftCircleLayer: CAShapeLayer!
   private var topRightCircleLayer: CAShapeLayer!
   private var bottomLeftCircleLayer: CAShapeLayer!
   private var bottomRightCircleLayer: CAShapeLayer!

imageView的约束
一个二个一个一个
设置我的视图

override func viewDidLoad() {
        super.viewDidLoad()

        scrollView.delegate = self

        setupView()

        addTapGestureRecognizer()
        addPinchGestureRecognizer()
        addRotateButton()
        addDeletePhotoButton()
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        borderLayer.path = UIBezierPath(rect: imageView.bounds).cgPath
        addConstraintsForItems()
        createCircles()
    }

    private func addConstraintsForItems() {
        imageViewTopConstraint = imageView.topAnchor.constraint(equalTo: view.topAnchor, constant: 180)
        imageViewBottomConstraint = imageView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -180)
        imageViewLeadingConstraint = imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 70)
        imageViewTrailingConstraint = imageView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -70)

        NSLayoutConstraint.activate([imageViewTopConstraint, imageViewBottomConstraint, imageViewLeadingConstraint, imageViewTrailingConstraint])
   }

    private func setupView() {
        view.addSubview(scrollView)
        view.addSubview(rotateButton)
        view.addSubview(deleteButton)

        scrollView.addSubview(imageView)

        borderLayer.fillColor = UIColor.clear.cgColor
        borderLayer.strokeColor = UIColor.black.cgColor
        borderLayer.lineWidth = 2
        borderLayer.isHidden = true
        imageView.layer.addSublayer(borderLayer)
    }

圆创建

private func updateCircles() {
        let topLeft = CGPoint(x: imageView.frame.minX, y: imageView.frame.minY)
        topLeftCircleLayer.position = topLeft
        let topRight = CGPoint(x: imageView.frame.maxX, y: imageView.frame.minY)
        topRightCircleLayer.position = topRight
        let bottomLeft = CGPoint(x: imageView.frame.minX, y: imageView.frame.maxY)
        bottomLeftCircleLayer.position = bottomLeft
        let bottomRight = CGPoint(x: imageView.frame.maxX, y: imageView.frame.maxY)
        bottomRightCircleLayer.position = bottomRight
        imageView.layer.insertSublayer(topLeftCircleLayer, at: 0)
        imageView.layer.insertSublayer(topRightCircleLayer, at: 1)
        imageView.layer.insertSublayer(bottomLeftCircleLayer, at: 2)
        imageView.layer.insertSublayer(bottomRightCircleLayer, at: 3)
    }

    private func createCircles() {
        topLeftCircleLayer = createCircle(at: CGPoint(x: imageView.frame.minX, y: imageView.frame.minY))
        topRightCircleLayer = createCircle(at: CGPoint(x: imageView.frame.maxX, y: imageView.frame.minY))
        bottomLeftCircleLayer = createCircle(at: CGPoint(x: imageView.frame.minX, y: imageView.frame.maxY))
        bottomRightCircleLayer = createCircle(at: CGPoint(x: imageView.frame.maxX, y: imageView.frame.maxY))
    }

    private func createCircle(at position: CGPoint) -> CAShapeLayer {
        let circle = CAShapeLayer()
        circle.path = UIBezierPath(arcCenter: position, radius: 10, startAngle: 0, endAngle: .pi * 2, clockwise: true).cgPath
        circle.fillColor = UIColor.systemPink.cgColor
        circle.strokeColor = UIColor.white.cgColor
        circle.lineWidth = 6
        circle.isHidden = !isCirclesVisible
        imageView.layer.addSublayer(circle)
        return circle
    }
    • 这是最重要的一步,我试着把角落拉起来**
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let touch = touches.first{

            let touchStart = touch.location(in: self.view)
            print(touchStart)

            resizeRect.topTouch = false
            resizeRect.leftTouch = false
            resizeRect.rightTouch = false
            resizeRect.bottomTouch = false

            if touchStart.y > imageView.frame.maxY - proxyFactor &&  touchStart.y < imageView.frame.maxY + proxyFactor {
                resizeRect.bottomTouch = true
                print("bottom")
            }

            if touchStart.x > imageView.frame.maxX - proxyFactor && touchStart.x < imageView.frame.maxX + proxyFactor {
                resizeRect.rightTouch = true
                print("right")
            }

            if touchStart.x > imageView.frame.minX - proxyFactor &&  touchStart.x < imageView.frame.minX + proxyFactor {
                resizeRect.leftTouch = true
                print("left")
            }

            if touchStart.y > imageView.frame.minY - proxyFactor &&  touchStart.y < imageView.frame.minY + proxyFactor {
                resizeRect.topTouch = true
                print("top")
            }

        }
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let touch = touches.first{
            let currentTouchPoint = touch.location(in: self.view)
            let previousTouchPoint = touch.previousLocation(in: self.view)

            let deltaX = currentTouchPoint.x - previousTouchPoint.x
            let deltaY = currentTouchPoint.y - previousTouchPoint.y

            if resizeRect.topTouch && resizeRect.leftTouch {
                if imageViewTopConstraint.constant + deltaY > 0 && imageViewLeadingConstraint.constant + deltaX > 0 {
                    imageViewTopConstraint.constant += deltaY
                    imageViewLeadingConstraint.constant += deltaX

                }
            }
            if resizeRect.topTouch && resizeRect.rightTouch {
                if imageViewTopConstraint.constant + deltaY > 0 && imageViewTrailingConstraint.constant - deltaX > 0 {
                    imageViewTopConstraint.constant += deltaY
                    imageViewTrailingConstraint.constant -= deltaX
                }
            }
            if resizeRect.bottomTouch && resizeRect.leftTouch {
                if imageViewBottomConstraint.constant - deltaY > 0 && imageViewLeadingConstraint.constant + deltaX > 0 {
                    imageViewLeadingConstraint.constant += deltaX
                    imageViewBottomConstraint.constant -= deltaY
                }
            }
            if resizeRect.bottomTouch && resizeRect.rightTouch {
                if imageViewBottomConstraint.constant - deltaY > 0 && imageViewTrailingConstraint.constant - deltaX > 0 {
                    imageViewTrailingConstraint.constant -= deltaX
                    imageViewBottomConstraint.constant -= deltaY
                }
            }

            UIView.animate(withDuration: 0.25, delay: 0, options: UIView.AnimationOptions.curveEaseIn) {
                self.view.layoutIfNeeded()
            }
        }
    }

编辑1:我对代码做了一些更新。我的应用程序终于能理解我触摸imageView的时候了,当我触摸一个角的时候,它能告诉我哪个角被触摸了,但是调整大小的功能不太好。有时候它能正常工作,但是调整大小的速度非常慢。在控制台里,它说我有这个错误:

Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<NSLayoutConstraint:0x600000cf8910 H:|-(65)-[UIImageView:0x13a707300]   (active, names: '|':UIView:0x13c20f220 )>",
    "<NSLayoutConstraint:0x600000ce0640 H:|-(70)-[UIImageView:0x13a707300]   (active, names: '|':UIView:0x13c20f220 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x600000ce0640 H:|-(70)-[UIImageView:0x13a707300]   (active, names: '|':UIView:0x13c20f220 )>

我尝试更新约束,但由于某种原因,它不允许我更新。我克隆了github project from a person that wrote a solution。他为约束创建了IBOutlets,据我所知,从IBOutlets创建的约束与我拥有的约束有某种不同。我如何解决约束问题?如果有人能注意到我的圆创建有什么问题,我将非常感激。现在我只看到图像中间下方的1 ...

n9vozmp4

n9vozmp41#

你的方法有几个问题...
首先,这些都不是:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    borderLayer.path = UIBezierPath(rect: imageView.bounds).cgPath
    addConstraintsForItems()
    createCircles()
}

viewDidLayoutSubviews()被调用了不止一次,如果你正在改变视图/约束,它将被调用很多次。
第二,您可能在使用代码设置(与使用@IBOutlet连接的Storyboard设置相反)时遇到麻烦,因为约束的顺序颠倒了。
在您的代码中,您设置了imageView上的所有4个约束,从imageView -> view开始。

// top and leading constraints need to be imageView -> view
imageViewTopConstraint = imageView.topAnchor.constraint(equalTo: view.topAnchor, constant: 180)
imageViewLeadingConstraint = imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 70)
    
// trailing and bottom constraints need to be view -> imageView
imageViewTrailingConstraint = view.trailingAnchor.constraint(equalTo: imageView.trailingAnchor, constant: 70)
imageViewBottomConstraint = view.bottomAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 180)

第三,您正在某些需要使用.bounds的地方使用.frame
下面是你的代码的修改版本。我不知道你是如何决定何时显示/隐藏角圆的,所以我添加了一个双击手势来激活/关闭“调整大小”模式:

class ResizeViewViewController: UIViewController {

    private var topLeftCircleLayer: CAShapeLayer!
    private var topRightCircleLayer: CAShapeLayer!
    private var bottomLeftCircleLayer: CAShapeLayer!
    private var bottomRightCircleLayer: CAShapeLayer!

    private var borderLayer: CAShapeLayer!

    private var imageViewTopConstraint: NSLayoutConstraint!
    private var imageViewBottomConstraint: NSLayoutConstraint!
    private var imageViewLeadingConstraint: NSLayoutConstraint!
    private var imageViewTrailingConstraint: NSLayoutConstraint!

    private var originalImageFrame: CGRect = .zero
    private var resizeRect = ResizeRect()

    private var proxyFactor: CGFloat = 10.0

    private var imageView = UIImageView()
    
    private var isResizing: Bool = false {
        didSet {
            // update circle positions and
            //  show or hide the circles and border
            updateCircles()
            topLeftCircleLayer.isHidden = !isResizing
            topRightCircleLayer.isHidden = !isResizing
            bottomLeftCircleLayer.isHidden = !isResizing
            bottomRightCircleLayer.isHidden = !isResizing
            borderLayer.isHidden = !isResizing
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
        
        setupView()

        addConstraintsForItems()
        
        createCircles()
        
        isResizing = false
        
        // let's use double-tap on the image view to
        //  toggle resizing
        let t = UITapGestureRecognizer(target: self, action: #selector(gotDoubleTap(_:)))
        t.numberOfTapsRequired = 2
        imageView.addGestureRecognizer(t)
        imageView.isUserInteractionEnabled = true

        // an instructions label at the top
        let v = UILabel()
        v.textAlignment = .center
        v.text = "Double-Tap image to toggle resizing mode."
        v.translatesAutoresizingMaskIntoConstraints = false
        // put it under the image view so it doesn't interfere
        view.insertSubview(v, at: 0)
        NSLayoutConstraint.activate([
            v.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20.0),
            v.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor),
        ])
        
    }
    
    @objc func gotDoubleTap(_ sender: Any?) {
        isResizing.toggle()
    }

    private func addConstraintsForItems() {

        // top and leading constraints need to be imageView -> view
        imageViewTopConstraint = imageView.topAnchor.constraint(equalTo: view.topAnchor, constant: 180)
        imageViewLeadingConstraint = imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 70)

        // trailing and bottom constraints need to be view -> imageView
        imageViewTrailingConstraint = view.trailingAnchor.constraint(equalTo: imageView.trailingAnchor, constant: 70)
        imageViewBottomConstraint = view.bottomAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 180)
        
        NSLayoutConstraint.activate([
            imageViewTopConstraint, imageViewBottomConstraint, imageViewLeadingConstraint, imageViewTrailingConstraint
        ])
    }

    private func setupView() {

        // add the image view
        imageView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(imageView)

        imageView.backgroundColor = .systemYellow

        // let's use the "swift" SF Symbol image
        if let img = UIImage(systemName: "swift") {
            imageView.image = img
            imageView.tintColor = .systemBlue
        }

        borderLayer = CAShapeLayer()
        borderLayer.fillColor = UIColor.clear.cgColor
        borderLayer.strokeColor = UIColor.black.cgColor
        borderLayer.lineWidth = 2
        borderLayer.isHidden = true
        imageView.layer.addSublayer(borderLayer)
        
    }

    private func updateCircles() {
        
        // we need to disable CALayer internal animations when
        //  changing the positions of the layers
        CATransaction.begin()
        CATransaction.setDisableActions(true)

        let topLeft = CGPoint(x: imageView.bounds.minX, y: imageView.bounds.minY)
        topLeftCircleLayer.position = topLeft
        let topRight = CGPoint(x: imageView.bounds.maxX, y: imageView.bounds.minY)
        topRightCircleLayer.position = topRight
        let bottomLeft = CGPoint(x: imageView.bounds.minX, y: imageView.bounds.maxY)
        bottomLeftCircleLayer.position = bottomLeft
        let bottomRight = CGPoint(x: imageView.bounds.maxX, y: imageView.bounds.maxY)
        bottomRightCircleLayer.position = bottomRight
        
        borderLayer.path = UIBezierPath(rect: imageView.bounds).cgPath
        
        CATransaction.commit()
        
    }

    private func createCircles() {
        // no need to pass "positions" here... they will be set when we show / update them
        topLeftCircleLayer = createCircle()
        topRightCircleLayer = createCircle()
        bottomLeftCircleLayer = createCircle()
        bottomRightCircleLayer = createCircle()

        // add the layers here
        imageView.layer.addSublayer(topLeftCircleLayer)
        imageView.layer.addSublayer(topRightCircleLayer)
        imageView.layer.addSublayer(bottomLeftCircleLayer)
        imageView.layer.addSublayer(bottomRightCircleLayer)
    }

    private func createCircle() -> CAShapeLayer {
        let circle = CAShapeLayer()
        circle.path = UIBezierPath(arcCenter: .zero, radius: 10, startAngle: 0, endAngle: .pi * 2, clockwise: true).cgPath
        circle.fillColor = UIColor.systemPink.cgColor
        circle.strokeColor = UIColor.white.cgColor
        circle.lineWidth = 6
        circle.isHidden = true
        return circle
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        
        if !isResizing { return() }
        
        if let touch = touches.first{
            
            let touchStart = touch.location(in: self.view)
            print(touchStart, imageView.frame)
            
            resizeRect.topTouch = false
            resizeRect.leftTouch = false
            resizeRect.rightTouch = false
            resizeRect.bottomTouch = false
            
            if touchStart.y > imageView.frame.maxY - proxyFactor &&  touchStart.y < imageView.frame.maxY + proxyFactor {
                resizeRect.bottomTouch = true
                print("bottom")
            }
            
            if touchStart.x > imageView.frame.maxX - proxyFactor && touchStart.x < imageView.frame.maxX + proxyFactor {
                resizeRect.rightTouch = true
                print("right")
            }
            
            if touchStart.x > imageView.frame.minX - proxyFactor &&  touchStart.x < imageView.frame.minX + proxyFactor {
                resizeRect.leftTouch = true
                print("left")
            }
            
            if touchStart.y > imageView.frame.minY - proxyFactor &&  touchStart.y < imageView.frame.minY + proxyFactor {
                resizeRect.topTouch = true
                print("top")
            }

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

        if !isResizing { return() }

        if let touch = touches.first{
            let currentTouchPoint = touch.location(in: self.view)
            let previousTouchPoint = touch.previousLocation(in: self.view)
            
            let deltaX = currentTouchPoint.x - previousTouchPoint.x
            let deltaY = currentTouchPoint.y - previousTouchPoint.y
            
            if resizeRect.topTouch {
                imageViewTopConstraint.constant += deltaY
            }
            if resizeRect.leftTouch {
                imageViewLeadingConstraint.constant += deltaX
            }
            if resizeRect.rightTouch {
                imageViewTrailingConstraint.constant -= deltaX
            }
            if resizeRect.bottomTouch {
                imageViewBottomConstraint.constant -= deltaY
            }

            // don't know why you would want to animate this?
            //UIView.animate(withDuration: 0.25, delay: 0, options: UIView.AnimationOptions.curveEaseIn, animations: {
            //  self.view.layoutIfNeeded()
            //}, completion: { (ended) in
            //
            //})

            // note: this can "lag" and not precisely match the image view frame
            
            self.updateCircles()
            
            //  we can dispatch it async to allow UIKit to set the
            //  image view's frame before we move the layers
            //  but we still get a little "lag"
            DispatchQueue.main.async {
                self.updateCircles()
            }

        }

    }

}

struct ResizeRect{
    var topTouch = false
    var leftTouch = false
    var rightTouch = false
    var bottomTouch = false
    var middelTouch = false
}

当你运行它的时候,你会注意到在拖动和调整大小的时候有一些“滞后”--参见代码中的注解。
类似的方法可能会发现它响应更快,而且更易于管理...
我们不添加“圆形图层”,而是添加“圆形视图”作为图像视图的子视图,然后我们可以设置图像视图角的约束,让自动布局处理所有的定位。
代码更少...利用自动布局...响应更快...
先运行上面的版本,然后给予这个:

class CircleView: UIView {
    
    // this allows us to use the "base" layer as a shape layer
    //  instead of adding a sublayer
    lazy var shapeLayer: CAShapeLayer = self.layer as! CAShapeLayer
    override class var layerClass: AnyClass {
        return CAShapeLayer.self
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() {
        shapeLayer.fillColor = UIColor.systemPink.cgColor
        shapeLayer.strokeColor = UIColor.white.cgColor
        shapeLayer.lineWidth = 6
    }
    override func layoutSubviews() {
        super.layoutSubviews()
        shapeLayer.path = UIBezierPath(ovalIn: bounds).cgPath
    }

}

class ResizeViewViewController: UIViewController {
    
    private var topLeftCircleView = CircleView()
    private var topRightCircleView = CircleView()
    private var bottomLeftCircleView = CircleView()
    private var bottomRightCircleView = CircleView()
    
    private var borderView = UIView()
    
    private var imageViewTopConstraint: NSLayoutConstraint!
    private var imageViewBottomConstraint: NSLayoutConstraint!
    private var imageViewLeadingConstraint: NSLayoutConstraint!
    private var imageViewTrailingConstraint: NSLayoutConstraint!
    
    private var originalImageFrame: CGRect = .zero
    private var resizeRect = ResizeRect()
    
    private var proxyFactor: CGFloat = 10.0
    
    private var imageView = UIImageView()
    
    private var isResizing: Bool = false {
        didSet {
            // show or hide the circles and image view border
            [topLeftCircleView, topRightCircleView, bottomLeftCircleView, bottomRightCircleView].forEach { v in
                v.isHidden = !isResizing
            }
            borderView.layer.borderWidth = isResizing ? 2.0 : 0.0
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
        
        setupView()
        
        addConstraintsForItems()
        
        createCircles()
        
        isResizing = false

        // let's use double-tap on the image view to
        //  toggle resizing
        let t = UITapGestureRecognizer(target: self, action: #selector(gotDoubleTap(_:)))
        t.numberOfTapsRequired = 2
        imageView.addGestureRecognizer(t)
        imageView.isUserInteractionEnabled = true

        // an instructions label at the top
        let v = UILabel()
        v.textAlignment = .center
        v.text = "Double-Tap image to toggle resizing mode."
        v.font = .systemFont(ofSize: 15.0, weight: .light)
        v.translatesAutoresizingMaskIntoConstraints = false
        // put it under the image view so it doesn't interfere
        view.insertSubview(v, at: 0)
        NSLayoutConstraint.activate([
            v.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20.0),
            v.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor),
        ])
        
    }
    
    @objc func gotDoubleTap(_ sender: Any?) {
        isResizing.toggle()
    }
    
    private func addConstraintsForItems() {
        
        // top and leading constraints need to be imageView -> view
        imageViewTopConstraint = imageView.topAnchor.constraint(equalTo: view.topAnchor, constant: 180)
        imageViewLeadingConstraint = imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 70)
        
        // trailing and bottom constraints need to be view -> imageView
        imageViewTrailingConstraint = view.trailingAnchor.constraint(equalTo: imageView.trailingAnchor, constant: 70)
        imageViewBottomConstraint = view.bottomAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 180)
        
        NSLayoutConstraint.activate([
            imageViewTopConstraint, imageViewBottomConstraint, imageViewLeadingConstraint, imageViewTrailingConstraint,

            // constrain all 4 sides of the borderView to the imageView
            borderView.topAnchor.constraint(equalTo: imageView.topAnchor),
            borderView.leadingAnchor.constraint(equalTo: imageView.leadingAnchor),
            borderView.trailingAnchor.constraint(equalTo: imageView.trailingAnchor),
            borderView.bottomAnchor.constraint(equalTo: imageView.bottomAnchor),
        ])
    }
    
    private func setupView() {

        // add the image view
        imageView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(imageView)

        imageView.backgroundColor = .systemYellow

        // add the borderView to the image view
        //  we'd like to just use the image view's layer border, but
        //  setting its border width draws on top of the circle subviews
        borderView.translatesAutoresizingMaskIntoConstraints = false
        imageView.addSubview(borderView)
        
        // let's use the "swift" SF Symbol image
        if let img = UIImage(systemName: "swift") {
            imageView.image = img
            imageView.tintColor = .systemBlue
        }
        
        // border view layer border starts at width: 0 (not showing)
        borderView.layer.borderColor = UIColor.black.cgColor
        borderView.layer.borderWidth = 0
        
    }
    

    private func createCircles() {

        // add the circle views to the image view
        //  constraining width: 20 and height = width
        [topLeftCircleView, topRightCircleView, bottomLeftCircleView, bottomRightCircleView].forEach { v in
            v.translatesAutoresizingMaskIntoConstraints = false
            v.widthAnchor.constraint(equalToConstant: 20.0).isActive = true
            v.heightAnchor.constraint(equalTo: v.widthAnchor).isActive = true
            // they start hidden
            v.isHidden = true
            imageView.addSubview(v)
        }
        
        // constrain circleViews to the image view corners
        NSLayoutConstraint.activate([
            topLeftCircleView.centerXAnchor.constraint(equalTo: imageView.leadingAnchor),
            topLeftCircleView.centerYAnchor.constraint(equalTo: imageView.topAnchor),
            
            topRightCircleView.centerXAnchor.constraint(equalTo: imageView.trailingAnchor),
            topRightCircleView.centerYAnchor.constraint(equalTo: imageView.topAnchor),
            
            bottomLeftCircleView.centerXAnchor.constraint(equalTo: imageView.leadingAnchor),
            bottomLeftCircleView.centerYAnchor.constraint(equalTo: imageView.bottomAnchor),
            
            bottomRightCircleView.centerXAnchor.constraint(equalTo: imageView.trailingAnchor),
            bottomRightCircleView.centerYAnchor.constraint(equalTo: imageView.bottomAnchor),
        ])

    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        
        // only want to drag-resize if the corner circles are showing
        if !isResizing { return() }
        
        if let touch = touches.first{
            
            let touchStart = touch.location(in: self.view)
            print(touchStart, imageView.frame)
            
            resizeRect.topTouch = false
            resizeRect.leftTouch = false
            resizeRect.rightTouch = false
            resizeRect.bottomTouch = false
            
            if touchStart.y > imageView.frame.maxY - proxyFactor &&  touchStart.y < imageView.frame.maxY + proxyFactor {
                resizeRect.bottomTouch = true
                print("bottom")
            }
            
            if touchStart.x > imageView.frame.maxX - proxyFactor && touchStart.x < imageView.frame.maxX + proxyFactor {
                resizeRect.rightTouch = true
                print("right")
            }
            
            if touchStart.x > imageView.frame.minX - proxyFactor &&  touchStart.x < imageView.frame.minX + proxyFactor {
                resizeRect.leftTouch = true
                print("left")
            }
            
            if touchStart.y > imageView.frame.minY - proxyFactor &&  touchStart.y < imageView.frame.minY + proxyFactor {
                resizeRect.topTouch = true
                print("top")
            }
            
        }
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        
        // only want to drag-resize if the corner circles are showing
        if !isResizing { return() }
        
        if let touch = touches.first{
            let currentTouchPoint = touch.location(in: self.view)
            let previousTouchPoint = touch.previousLocation(in: self.view)
            
            let deltaX = currentTouchPoint.x - previousTouchPoint.x
            let deltaY = currentTouchPoint.y - previousTouchPoint.y
            
            if resizeRect.topTouch {
                imageViewTopConstraint.constant += deltaY
            }
            if resizeRect.leftTouch {
                imageViewLeadingConstraint.constant += deltaX
            }
            if resizeRect.rightTouch {
                imageViewTrailingConstraint.constant -= deltaX
            }
            if resizeRect.bottomTouch {
                imageViewBottomConstraint.constant -= deltaY
            }
            
            // don't know why you would want to animate this?
            //UIView.animate(withDuration: 0.25, delay: 0, options: UIView.AnimationOptions.curveEaseIn, animations: {
            //  self.view.layoutIfNeeded()
            //}, completion: { (ended) in
            //
            //})

        }
        
    }
    
}

struct ResizeRect{
    var topTouch = false
    var leftTouch = false
    var rightTouch = false
    var bottomTouch = false
    var middelTouch = false
}

相关问题