【问题标题】:Want to restrict area of pan gesture on one imageView swift 5想要限制一个imageView swift 5上的平移手势区域
【发布时间】:2023-03-10 05:40:02
【问题描述】:

我有一个具有 2 个手势识别器的图像视图 1)捏 2)平移

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

这是捏和平移手势的代码

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

【问题讨论】:

  • 您是否有理由不使用 UIScrollView 的内置缩放/平移功能?
  • 是的,我们必须在 imageview 上绘图,所以我们不使用滚动视图

标签: ios swift uigesturerecognizer


【解决方案1】:

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

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,而drag-view的宽度是200,那么MAX centerX就是100,MIN centerX就是Zero

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

尝试使用它作为你的 Pan Gesture 处理程序:

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

编辑

为了防止 Pinch Gesture 将视图缩小到小于其 superView 帧,我们可以将手势中的新缩放值应用到视图 frameCGRect,然后再将其应用到视图。

然后,仅当生成的矩形不小于 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
    
}

【讨论】:

  • 这很有魅力查看该图像视图后面的背景视图
  • @HetaliBhimjiyani - 是的,我想这将是你的下一个问题。请参阅我的答案的编辑
  • 哇,你在我面前这么认为是伟人。非常感谢您的努力。非常感谢??
猜你喜欢
  • 2012-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-07
  • 1970-01-01
相关资源
最近更新 更多