【问题标题】:How to fill overlapped parts in UIBezierPath?如何填充 UIBezierPath 中的重叠部分?
【发布时间】:2019-01-04 11:03:13
【问题描述】:

我想在裁剪矩形的周围绘制蒙版,它在角落有夹点,我试图用组合的 UIBezierPath 填充矩形内部,例如:4 个圆形和 1 个矩形,而不是将此路径分配给 CAShapeLayer 以将其用作在我看来子层。到目前为止,它填充所需区域只是重叠部分(当我们在矩形上附加圆圈时)未填充(所有角落的四分之一三角形),所以我尝试使用 combinedPath.usesEvenOddFillRule = false - combinedPath.fill() - combinedPath.close() 但它们都没有使用我!所以我需要填写这些部分也有人可以帮助我吗?

你可以从这个link查看图片

我的代码:

    // draw mask
    let path = UIBezierPath(rect: viewBackground.bounds)

    let maskRect = CGRect(x: imgView.frame.origin.x + roiRect.minX * rate, y: imgView.frame.origin.y + roiRect.minY * rate, width: roiRect.width * rate, height: roiRect.height * rate)
    // First apth is for rectangle
    let rectPath = UIBezierPath(rect: maskRect)
    path.append(rectPath)

    // and these paths for corners
    let cornerMaskCircleSize: CGFloat = circleSize/2
    let maskTopLeftCornerPath = UIBezierPath(ovalIn: CGRect(x: maskRect.minX - cornerMaskCircleSize/2, y: maskRect.minY - cornerMaskCircleSize/2, width: cornerMaskCircleSize, height: cornerMaskCircleSize))
    let maskTopRightCornerPath = UIBezierPath(ovalIn: CGRect(x: maskRect.maxX - cornerMaskCircleSize/2, y: maskRect.minY - cornerMaskCircleSize/2, width: cornerMaskCircleSize, height: cornerMaskCircleSize))
    let maskBottomRightCornerPath = UIBezierPath(ovalIn: CGRect(x: maskRect.maxX - cornerMaskCircleSize/2, y: maskRect.maxY - cornerMaskCircleSize/2, width: cornerMaskCircleSize, height: cornerMaskCircleSize))
    let maskBottomLeftCornerPath = UIBezierPath(ovalIn: CGRect(x: maskRect.minX - cornerMaskCircleSize/2, y: maskRect.maxY - cornerMaskCircleSize/2, width: cornerMaskCircleSize, height: cornerMaskCircleSize))

    // Combining all of them in one path
    path.append(maskTopLeftCornerPath)
    path.append(maskTopRightCornerPath)
    path.append(maskBottomRightCornerPath)
    path.append(maskBottomLeftCornerPath)
    path.usesEvenOddFillRule = true
    path.fill()
    path.close()

    cropMask.removeFromSuperlayer()
    cropMask.bounds = viewBackground.frame
    cropMask.position = viewBackground.center
    cropMask.path = path.cgPath
    cropMask.fillRule = .evenOdd
    cropMask.fillColor = UIColor.init(hexString: "#212f41").cgColor
    cropMask.opacity = 0.6

    viewBackground.layer.addSublayer(cropMask)

【问题讨论】:

    标签: swift uikit drawing uibezierpath


    【解决方案1】:

    经过 5 个小时的研究,我终于找到了这个 extension,它以不同的方式解决了我的问题,这个扩展有助于绘制四分之三的圆,所以我用它来绘制从矩形角边为空的圆。

    这是一个使用示例代码:

    fileprivate func drawMask() {
    
        let rectPath = UIBezierPath(rect: CGRect(x: 100, y: 200, width: 175, height: 150))
        let leftTopCornerPath = UIBezierPath(quarterCircleCentre: CGPoint(x: 100, y: 200), radius: 10, quadrant: .BottomRightThreeQuarterCircle)
        let rightTopCornerPath = UIBezierPath(quarterCircleCentre: CGPoint(x: 275, y: 200), radius: 10, quadrant: .BottomLeftThreeQuarterCircle)
        let leftBottomCornerPath = UIBezierPath(quarterCircleCentre: CGPoint(x: 100, y: 350), radius: 10, quadrant: .TopRightThreeQuarterCircle)
        let rightBottomCornerPath = UIBezierPath(quarterCircleCentre: CGPoint(x: 275, y: 350), radius: 10, quadrant: .TopLeftThreeQuarterCircle)
    
        let combined = UIBezierPath(rect: self.view.frame)
        combined.append(rectPath)
        combined.append(leftTopCornerPath)
        combined.append(rightTopCornerPath)
        combined.append(leftBottomCornerPath)
        combined.append(rightBottomCornerPath)
    
        let maskLayer = CAShapeLayer()
        maskLayer.bounds = self.view.bounds
        maskLayer.position = self.view.center
        maskLayer.path = combined.cgPath
        maskLayer.fillRule = .evenOdd
        maskLayer.fillColor = UIColor.black.cgColor
        maskLayer.opacity = 0.5
    
        self.view.layer.addSublayer(maskLayer)
    
    }
    

    扩展

    extension UIBezierPath {
    
    
    enum QuarterCircleQuadrant {
        case TopLeft, BottomLeft, TopRight, BottomRight, TopLeftThreeQuarterCircle, BottomRightThreeQuarterCircle, BottomLeftThreeQuarterCircle, TopRightThreeQuarterCircle
        var startAngle: CGFloat {
            switch self {
            case .BottomLeft:
                return CGFloat(Double.pi)
            case .BottomLeftThreeQuarterCircle:
                return CGFloat(Double.pi)
            case .TopLeft:
                return CGFloat(Double.pi)
            case .BottomRight:
                return 0
            case .TopRight:
                return 0
            case .TopRightThreeQuarterCircle:
                return 0
            case .TopLeftThreeQuarterCircle:
                return CGFloat(Double.pi)
            case .BottomRightThreeQuarterCircle:
                return 0
            }
    
        }
        var endAngle: CGFloat {
            switch self {
            case .BottomLeft:
                return CGFloat(Double.pi/2)
            case .BottomLeftThreeQuarterCircle:
                return CGFloat(Double.pi/2)
            case .TopLeft:
                return CGFloat(Double.pi) * 1.5
            case .BottomRight:
                return CGFloat(Double.pi/2)
            case .TopRight:
                return CGFloat(Double.pi) * 1.5
            case .TopRightThreeQuarterCircle:
                return CGFloat(Double.pi) * 1.5
            case .TopLeftThreeQuarterCircle:
                return CGFloat(Double.pi) * 1.5
            case .BottomRightThreeQuarterCircle:
                return CGFloat(Double.pi/2)
            }
    
    
        }
    
        var clockwise: Bool {
            switch self {
            case .BottomLeft:
                return false
            case .TopLeft:
                return true
            case .BottomRight:
                return true
            case .TopRight:
                return false
            case .BottomLeftThreeQuarterCircle:
                return true
            case .TopRightThreeQuarterCircle:
                return true
            case .TopLeftThreeQuarterCircle:
                return false
            case .BottomRightThreeQuarterCircle:
                return false
            }
    
    
        }
    
    }
    
    convenience init(quarterCircleCentre centre:CGPoint, radius:CGFloat, quadrant:QuarterCircleQuadrant)
    {
        self.init()
        self.move(to: CGPoint(x: centre.x, y:centre.y))
        self.addArc(withCenter: centre, radius:radius, startAngle:quadrant.startAngle, endAngle: quadrant.endAngle, clockwise:quadrant.clockwise)
        self.close()
    }
    }
    

    结果图片 link

    【讨论】:

      猜你喜欢
      • 2017-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多