我已经创建了一个定制的UIView,它绘制UIBezierPath,将其分配给CAShapeLayer,然后将其屏蔽到UIView的根层.现在,我try 使用以下代码确定不同的UIView是否与该自定义视图中的Bezier路径的任何部分相交(或重叠):

    let customView = … // define UICustomView

    let purpleView = UIView(frame: CGRect(x: 30, y: 500, width: 100, height: 50))
    purpleView.backgroundColor = UIColor.purple
    self.view.addSubview(purpleView)
    
    if purpleView.frame.intersects((customView.shapeLayer.path?.boundingBoxOfPath)!) == true { 
        print("Overlapping")
    } else {
        print("Not overlapping")
    }

唯一的问题是,只有当PurpleView位于部分正方形的左上角时,它才会返回True.下面的位置返回FALSE:

(如果与任何绿色重叠,则返回TRUE,否则返回FALSE.我只画了正方形的3条边,并故意将填充物留空)

enter image description here

以下是自定义视图的代码

class CustomView : UIView {

private var _path : UIBezierPath!
public let shapeLayer = CAShapeLayer()

override init(frame: CGRect) {
    super.init(frame: frame)
    self._setup()
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    self._setup()
}

private func _setup() {
    self._createSquare()
}

private func _createSquare() { 
    self._path = UIBezierPath()
    self._path.move(to: CGPoint(x: 0.0, y: 0.0))
    self._path.addLine(to: CGPoint(x: 0.0, y: self.frame.size.height))
    self._path.addLine(to: CGPoint(x: self.frame.size.width, y: self.frame.size.height))
    self._path.addLine(to: CGPoint(x: self.frame.size.width, y: 0.0))
    //self._path.close()
    
    
    
    self.shapeLayer.path = self._path.cgPath
    self.shapeLayer.lineWidth = 10
    self.shapeLayer.strokeColor = UIColor.green.cgColor 
    self.backgroundColor = UIColor.green
    self.shapeLayer.fillColor = nil 
    self.layer.mask = self.shapeLayer   
}
}

有没有办法实现这一点?我意识到使用Frame.intersects()函数可能不是正确的方法.

推荐答案

您正在混淆坐标空间.boundBoxOfPathCustomView‘S坐标空间中,而purpleView.frameself.view坐标空间中.仅当路径位于同一坐标空间时,才应比较路径.UICoordinateSpace中的各种convert种方法可用于在坐标空间之间进行转换.

if let pathBounds = customView.shapeLayer.path?.boundingBoxOfPath,
   self.view.convert(purpleView.frame, to: customView).intersects(pathBounds) {
    print("Overlapping")
} else {
    print("Not overlapping")
}

请注意,这将判断两个矩形是否重叠.对于这样的情况,它也将返回True:

enter image description here

绿色的"矩形"completely covers是紫色的矩形,那也是一种相交.

如果只想判断紫色矩形是否与绿色lines相交,可以从绿色路径创建一条新路径,这样,当填充绿色时,结果与stroked绿色路径相同.请参见copy(strokingWithWidth:lineCap:lineJoin:miterLimit:transform:).

然后,从purpleView.frame创建一条矩形路径,并使用CGPath.intersects判断新路径和矩形路径是否相交.

let purpleViewPath = CGPath(rect: self.view.convert(purpleView.frame, to: customView), transform: nil)
if let path = customView.shapeLayer.path?.copy(
    strokingWithWidth: customView.shapeLayer.lineWidth,

    // these are the default values for a CGShapeLayer.
    // you can also try converting the values from the corresponding properties in CGShapeLayer
    lineCap: .butt,
    lineJoin: .miter,
    miterLimit: 10
),
   purpleViewPath.intersects(path, using: .evenOdd) {
    print("Overlapping")
} else {
    print("Not overlapping")
}

Swift相关问答推荐

@ MainActor + Combine不一致的编译器错误

在`NavigationStack`中使用`SafeAreaInset`修饰符时出现SwiftUI异常行为

ARRaycast Query和前置摄像头(ARFaceTrackingConfiguration)

如何增加 NSStatusBar 图像大小?

循环字典中的数组

使用`JSONSerialiser`时,省略通用可选项

SwiftUI .task 视图修改器:运行在哪个线程中?

在 struct 中的序列和非序列泛型函数之间进行 Select

SwiftUI 视图的默认成员初始化器 VS 自定义初始化器

Vapor 4,如何按外键过滤?

Vapor, fluent 使用 PostgreSQL 保存/创建复杂模型

组合 flatMap 不会返回预期的上下文结果类型

快速的 AES 加密

在 Swift 4 中,如何删除基于块的 KVO 观察者?

Swift - 导入我的 swift 类

如何轻松删除领域中的所有对象

iOS/Swift:如何检测 UITextField 上的touch 动作

如何在今天的扩展(iOS)中访问 CoreData 模型

swift中静态函数和单例类的区别

tableView 部分标题消失 SWIFT