想在一个 imageView 上限制平移手势的区域 swift 5

Want to restrict area of pan gesture on one imageView swift 5

我有一个 imageview,它有 2 个 gestureRecognizers 1)捏 2)潘

我可以捏合图像并使用比例缩放 属性 我无法实现的是,当我缩放该图像并拖动到所有 4 个边时,我可以拖动图像并且我能够看到 imageview 后面的背景视图 想要限制 imageview 的拖动直到显示 zommed 图像

这是捏合和平移手势的代码

  @objc func pinchRecognized(pinch: UIPinchGestureRecognizer) {

            if let view = pinch.view {
                view.transform = view.transform.scaledBy(x: pinch.scale, y: pinch.scale)
                pinch.scale = 1
            }
        }
    
    @objc func PangestureMethod(gestureRecognizer: UIPanGestureRecognizer){
       guard gestureRecognizer.view != nil else {return}
       let piece = gestureRecognizer.view!
  
    
       let translation = gestureRecognizer.translation(in: piece.superview)
        
       if gestureRecognizer.state == .began {
          self.initialCenter = piece.center
       }
       if gestureRecognizer.state != .cancelled {
          let newCenter = CGPoint(x: initialCenter.x + translation.x, y: initialCenter.y + translation.y)
          piece.center = newCenter
       }
       else {
          piece.center = initialCenter
       }
    }

首先,重置平移手势的翻译(可能)更容易,因此我们计算相对 移动:

if gestureRecognizer.state != .cancelled {
    
    // translation will be + or - a small number of points
    // do what's needed to move the view

    // reset recognizer
    gestureRecognizer.setTranslation(.zero, in: superV)

}

否则,假设您向右拖动(平移)300 磅,但视图只能移动 20 磅,然后它不会开始向左移动,直到您向左拖动 280 磅。

所以,当水平拖动时我们想在拖动视图位于其 superView 的左边缘或右边缘时停止...

  • 计算 MAX centerX 位置
    • 这将是拖动视图宽度的 1/2
  • 计算 MIN centerX 位置
    • 这将是 superView 的宽度减去拖动视图宽度的 1/2

例如,如果 superView 的宽度为 100,拖动视图的宽度为 200,则 MAX centerX 将为 100,MIN centerX 将为 Zero.

然后我们对 centerY 位置做同样的事情。

尝试将其用作您的平移手势处理程序:

@objc func PangestureMethod(gestureRecognizer: UIPanGestureRecognizer){
    
    // unwrap the view from the gesture
    // AND
    // unwrap that view's superView
    guard let piece = gestureRecognizer.view,
          let superV = piece.superview
    else {
        return
    }
    
    let translation = gestureRecognizer.translation(in: superV)
    
    if gestureRecognizer.state == .began {
        self.initialCenter = piece.center
    }
    if gestureRecognizer.state != .cancelled {

        // what the new centerX and centerY will be
        var newX: CGFloat = piece.center.x + translation.x
        var newY: CGFloat = piece.center.y + translation.y

        // MAX centerX is 1/2 the width of the piece's frame
        let mxX = piece.frame.width * 0.5
        
        // MIN centerX is Width of superView minus 1/2 the width of the piece's frame
        let mnX = superV.bounds.width - piece.frame.width * 0.5
        
        // make sure new centerX is neither greater than MAX nor less than MIN
        newX = max(min(newX, mxX), mnX)
        
        // MAX centerY is 1/2 the height of the piece's frame
        let mxY = piece.frame.height * 0.5
        
        // MIN centerY is Height of superView minus 1/2 the height of the piece's frame
        let mnY = superV.bounds.height - piece.frame.height * 0.5
        
        // make sure new centerY is neither greater than MAX nor less than MIN
        newY = max(min(newY, mxY), mnY)
        
        // set the new center
        piece.center = CGPoint(x: newX, y: newY)
        
        // reset recognizer
        gestureRecognizer.setTranslation(.zero, in: superV)

    }
    else {
        piece.center = initialCenter
    }
}

编辑

为了防止捏合手势将视图缩小到小于其 superView 框架,我们可以将手势的新缩放值应用到视图的 框架 [=] 的 CGRect 57=] 在将其应用到视图之前。

然后,如果生成的矩形不小于 superView 的框架,则仅将缩放应用于视图。

试一试:

@objc func pinchRecognized(pinch: UIPinchGestureRecognizer) {

    // unwrap the view from the gesture
    // AND
    // unwrap that view's superView
    guard let piece = pinch.view,
          let superV = piece.superview
    else {
        return
    }

    // this is a bit verbose for clarity
    
    // get the new scale
    let sc = pinch.scale
    
    // get current frame of "piece" view
    let currentPieceRect = piece.frame
    
    // apply scaling transform to the rect
    let futureRect = currentPieceRect.applying(CGAffineTransform(scaleX: sc, y: sc))
    
    // if the resulting rect's width will be
    //  greater-than-or-equal to superView's width
    if futureRect.width >= superV.bounds.width {
        // go ahead and scale the piece view
        piece.transform = piece.transform.scaledBy(x: sc, y: sc)
    }
    pinch.scale = 1
    
}