使用 UIPanGestureRecognizer 缩放和移动 UIView

Posted

技术标签:

【中文标题】使用 UIPanGestureRecognizer 缩放和移动 UIView【英文标题】:Scale and move an UIView using UIPanGestureRecognizer 【发布时间】:2017-11-09 11:01:21 【问题描述】:

我有一个 UIView A。我在视图 A 上放了一个图标,并尝试使用平移手势来缩放和移动此视图 A。

我尝试了很多解决方案,但我无法做到。

请建议帮助我?

更多详情:

我会添加更多细节。

我有视图 A,在自身视图上添加子视图。我希望当我在视图 A 上绘制 panGestureRegonizer 时,视图 A 将跟随绘制移动。

并且在移动视图 A 时会缩放。当视图移动到屏幕的顶部/左侧/底部/右侧时,视图 A 将缩小,当视图移动到屏幕中心时,视图 A 将放大。

【问题讨论】:

你能补充更多细节吗? 我已经添加了更多细节,请再次检查帮助我。 @Archmede 【参考方案1】:

假设您有vc - ViewController,而您的UIView Avc 的子视图。您可以将UIPanGestureRecognizer 添加到A。然后将 panGestureRegonizer 作为操作拖到您的vc

@IBAction func panGestureAction(_ sender: UIPanGestureRecognizer) 
        //your code here

sender,您可以检查viewlocationstate 的操作。 state 在某些情况下可能会影响您的代码,具体取决于您要实现的目标。

那你需要把action修改成这样:

@IBAction func panGestureAction(_ sender: UIPanGestureRecognizer) 
        UIView.animateKeyframes(withDuration: 0.1, delay: 0, options: UIViewKeyframeAnimationOptions.calculationModeLinear, animations: 
            let location = sender.location(in: sender.view?.superview)
            sender.view?.center = location
        )
    

这里sender.view?.superview 等于vc.view。此代码 sn-p 将检测平移手势,然后将移动A,因此A.center 与手势的位置相匹配。请注意,持续时间 0.1 为运动提供平滑的动画效果。

这将为您提供带有平移手势的“移动”功能。

EDIT 进行缩放:

逻辑:您有centerxy 的坐标系(CS)。当用户使用平移手势时,他/她在 CS 中生成点序列。所以我们的任务是测量CS中心和用户点之间的距离。当我们有最远的距离时,我们可以计算缩放视图的比例因子。

var center: CGPoint! //center of the CS
let maxSize: CGSize = CGSize.init(width: 100, height: 100) // maximum size of our scaling view
var maxLengthToCenter: CGFloat! //maximum distance from the center of the CS to the furthest point in the CS

private func prepareForScaling() 
    self.center = self.view.center //we set the center of our CS to equal the center of the VC's view
    let frame = self.view.frame
    //the furthest distance in the CS is the diagonal, and we calculate it using pythagoras theorem
    self.maxLengthToCenter = (frame.width*frame.width + frame.height*frame.height).squareRoot() 

然后我们需要调用我们的设置函数来让我们的数据为扩展功能做好准备 - 我们可以在 viewDidLoad 中执行此操作:

override func viewDidLoad() 
    super.viewDidLoad()  
    self.prepareForScaling()

然后我们需要一个辅助函数来计算我们视图的缩放大小,用于用户平移手势在屏幕上的当前位置。

private func scaledSize(for location: CGPoint) -> CGSize 
    //calculate location x,y differences from the center
    let xDifference = location.x - self.center.x
    let yDifference = location.y - self.center.y

    //calculate the scale factor - note that this factor will be between 0.0(center) and 0.5(diagonal - furthest point)    
    //It is due our measurement - from center to view's edge. Consider multiplying this factor with your custom constant.
    let scaleFactor = (xDifference*xDifference + yDifference*yDifference).squareRoot()/maxLengthToCenter
    //create scaled size with maxSize and current scale factor
    let scaledSize = CGSize.init(width: maxSize.width*(1-scaleFactor), height: maxSize.height*(1-scaleFactor))

    return scaledSize

最后,我们需要修改平移手势动作来改变A的大小:

@IBAction func panGestureAction(_ sender: UIPanGestureRecognizer) 
    UIView.animateKeyframes(withDuration: 0.1, delay: 0, options: UIViewKeyframeAnimationOptions.calculationModeLinear, animations: 

        let location = sender.location(in: sender.view?.superview)

        sender.view?.frame = CGRect.init(origin: CGPoint.init(x: 0, y: 0), size: self.scaledSize(for: location))

        sender.view?.center = location
    )

【讨论】:

非常感谢。对于使用 UIPanGestureRecognizer 移动视图,我做得很好。我对你的解决方案也做了同样的事情。我遇到了规模问题。我已经添加了更多细节,请再次检查帮助我。 稍后我将使用缩放功能更新答案。

以上是关于使用 UIPanGestureRecognizer 缩放和移动 UIView的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用 UIPanGestureRecognizer 移动对象时会有延迟?

UIPanGestureRecognizer ***视图未获取事件,子视图使用它们

在 UITableView 上滑动删除以使用 UIPanGestureRecognizer

在 UIPanGestureRecognizer 中使用velocityInView

使用 UIPanGestureRecognizer 拖动 + 旋转触摸下车

使用 UIPanGestureRecognizer 移动和缩放 UIView