让UIPinchGestureRecognizer像在Instagram故事中的贴纸一样在imageview之外工作

时间:2018-04-24 07:07:08

标签: ios swift uigesturerecognizer uipinchgesturerecognizer

我正在开发一个图像编辑应用程序。当贴纸添加到视图中时,pinchGesture可用于缩放。问题是当imageView(贴纸)非常小时,gesture非常难以使用。我需要能够在贴纸之外pinch并仍然缩放imageView

然后我将pinchGesture添加到self.view并检测到它的触摸;如果手指的直线与imageView相交,则应用pinchGesture。这样可以正常工作,直到添加了多个贴纸(imageViews)并且gesture同时在多个贴纸上工作。

因此,我计算了每个视图从手指到矩形的交点距离,最长距离的视图将获得pinchGesture

这不会一直有效。 这是代码:

@objc func pinched(sender: UIPinchGestureRecognizer){
    slider.isUserInteractionEnabled = false
    if sender.numberOfTouches == 2 && sender.state != .ended{

        selectedView = []
        let finger1 = sender.location(ofTouch: 0, in: self.view)
        let finger2 = sender.location(ofTouch: 1, in: self.view)

        for subview in self.view.subviews{
            if subview is UIImageView{

                let rect = subview.frame
                let width = rect.size.width
                let height = rect.size.height

                let Ax = rect.origin.x
                let Ay = rect.origin.y

                let Bx = rect.origin.x + width
                let By = rect.origin.y

                let Dx = rect.origin.x
                let Dy = rect.origin.y  + height

                let Cx = rect.origin.x + height
                let Cy = rect.origin.y + width

                let A = CGPoint(x: Ax, y: Ay)
                let B = CGPoint(x: Bx, y: By)
                let C = CGPoint(x: Cx, y: Cy)
                let D = CGPoint(x: Dx, y: Dy)

                let lineToAB = getIntersectionOfLines(line1: (finger1, finger2), line2: (A, B))
                let lineToBC = getIntersectionOfLines(line1: (finger1, finger2), line2: (B, C))
                let lineToCD = getIntersectionOfLines(line1: (finger1, finger2), line2: (C, D))
                let lineToAD = getIntersectionOfLines(line1: (finger1, finger2), line2: (A, D))

                var dx: CGFloat!
                if lineToAB != CGPoint.zero || lineToBC != CGPoint.zero || lineToCD != CGPoint.zero || lineToAD != CGPoint.zero{
                    print("touched")

                    touched = true
                    if lineToAB != CGPoint.zero{
                        dx = distance(lineToAB, lineToCD)
                    }else if lineToBC != CGPoint.zero{
                        dx = distance(lineToBC, lineToAD)
                    }else if lineToCD != CGPoint.zero{
                        dx = distance(lineToAB, lineToCD)
                    }else if lineToAD != CGPoint.zero{
                        dx = distance(lineToAD, lineToBC)
                    }else{
                        dx = 0.0
                    }
                }else{
                    dx = 0.0
                    touched = false
                }
                selectedView.append(selectedViews(distance: dx, view: subview))
            }
        }
        var max: CGFloat = 0.0
        var viewtoscale: UIView!
        for item in selectedView{
            if item.distance > max{
                max = item.distance
                viewtoscale = item.view
            }
        }
        if viewtoscale != nil{
            if viewtoscale != self.slider || viewtoscale != tempImageView || viewtoscale != drawView{
                if viewtoscale is UIImageView{
                     viewtoscale.transform = viewtoscale.transform.scaledBy(x: sender.scale, y: sender.scale)
                } 
            }   
        }
        sender.scale = 1
    }
    }

获取交叉点和距离的功能:

func getIntersectionOfLines(line1: (a: CGPoint, b: CGPoint), line2: (a: CGPoint, b: CGPoint)) -> CGPoint {

let distance = (line1.b.x - line1.a.x) * (line2.b.y - line2.a.y) - (line1.b.y - line1.a.y) * (line2.b.x - line2.a.x)
if distance == 0 {
    print("error, parallel lines")
    return CGPoint.zero
}
let u = ((line2.a.x - line1.a.x) * (line2.b.y - line2.a.y) - (line2.a.y - line1.a.y) * (line2.b.x - line2.a.x)) / distance
let v = ((line2.a.x - line1.a.x) * (line1.b.y - line1.a.y) - (line2.a.y - line1.a.y) * (line1.b.x - line1.a.x)) / distance

if (u < 0.0 || u > 1.0) {
    print("error, intersection not inside line1")
    return CGPoint.zero
}
if (v < 0.0 || v > 1.0) {
    print("error, intersection not inside line2")
    return CGPoint.zero
}

return CGPoint(x: line1.a.x + u * (line1.b.x - line1.a.x), y: line1.a.y + u * (line1.b.y - line1.a.y))
}

func distance(_ a: CGPoint, _ b: CGPoint) -> CGFloat {
let xDist = a.x - b.x
let yDist = a.y - b.y
return CGFloat(sqrt((xDist * xDist) + (yDist * yDist)))
}

1 个答案:

答案 0 :(得分:0)

您可以为每个imageView设置标记,并将 selectedSticker 声明为Int,当用户在贴纸中将selectedSticker设置为其标记时,然后只需缩放所选贴纸。