滑动手势时将视图更改为圆圈,iOS、Swift

Change view to a circle on swipe gesture, iOS, Swift

我正在尝试通过滑动手势(向任何方向,快或慢)将视图缩小为圆圈,类似于 WhatsApp videoCall 视图的体验。查看下面的图片,了解我想要实现的目标。

我认为我需要使用滑动手势来实现此目的,我已将滑动手势添加到 videoView,我不确定下一步该怎么做。

在 viewDidLoad 中我有以下内容

videoView.addGestureRecognizer(UISwipeGestureRecognizer(target: self, action: #selector(self.minimiseView) ))

我想我需要使用手势定位?而且我还需要设置随着滑动而增加的角半径。有人可以告诉我如何实现这一目标吗?

func minimiseView(gesture: UISwipeGestureRecognizer){
        let location = gesture.location(in: self.view)
    }

您基本上想要执行以下步骤:

  1. 捕捉起始手势位置
  2. 在滑动过程中,测量与原始滑动的距离
  3. 使用这个距离来增加相机视野的角半径
    • 例如设置 cornerRadius = distanceSwiped
  4. 一旦圆角半径达到一定量(且视图为圆形),捕获当前手势位置
  5. 使用此值再次开始跟踪运动并使用它来减小视图的宽度
  6. 当视图足够小时将其关闭

以下是完成此操作的基本设置:

enum VideoDismissState {
    case cornerRadiusChanging, sizeChanging, complete
}

var initialGesturePosition: CGPoint = .zero
var maxCornerRadiusGesturePosition: CGPoint = .zero
var dismissState: VideoDismissState = .complete

func minimiseView(_ gesture: UISwipeGestureRecognizer) {
    let location = gesture.location(in: videoView)

    switch gesture.state {
    case .began:
        initialGesturePosition = gesture.location(in: videoView)
        dismissState = .cornerRadiusChanging
    case .changed:
        let currentPosition = gesture.location(in: videoView)

        switch dismissState {
        case cornerRadiusChanging:
            let swipeDistance = distance(between: initialGesturePosition, and: currentPosition)
            // play around with this formula to see what feels right
            videoView.layer.cornerRadius = swipeDistance / 2

            // at a certain point, switch to changing the size
            if swipeDistance >= videoView.width / 2 {
                maxCornerRadiusGesturePosition = currentPosition
                dismissState = .sizeChanging
            }
        case sizeChanging:
            let swipeDistance = distance(between: maxCornerGesturePosition, and: currentPosition)
            // again try different things to see what feels right here
            let scaleFactor = 50 / swipeDistance

            videoView.layer.transform = CGAffineTransform(scaledX: scaleFactor, y: scaleFactor

            if scaleFactor <= 0.2 {
                dismissState = .complete
            }
        case complete:
            // reset values
            initialGesturePosition = .zero
            maxCornerRadiusGesturePosition = .zero

            // dismiss videoView
            // for example: videoView.isHidden = true OR videoView.removeFromSuperview()
        }
    case .ended:
        // if the gesture ends too soon you may want to animate the view back to full screen
    }
}

/// Measure distance between two points
func distance(between first: CGPoint, and second: CGPoint) -> CGFloat {
    return sqrt((first.x - second.x) ^ 2 + (first.y - second.y) ^ 2)
}

这可能不会完全奏效,因为我还没有测试过,但基本的想法应该足以让你入门。