Как заполнить перекрывающиеся части в UIBezierPath? - PullRequest
0 голосов
/ 04 января 2019

Я хотел бы нарисовать маску вокруг прямоугольника кадрирования, чтобы он имел ручки в углах, и я пытаюсь заполнить внутри прямоугольника комбинированным UIBezierPath, например: 4 круга и 1 прямоугольник, чем назначать этот путь CAShapeLayer, чтобы использовать его какподслой на мой взгляд.Пока все хорошо, он заполняет желаемую область только перекрывающимися частями (когда мы добавляем круги по прямоугольнику), не заполненными (четверть треугольника во всем углу), поэтому я попытался использовать combinedPath.usesEvenOddFillRule = false - combinedPath.fill() - combinedPath.close(), но ни одна из них не работала смне!Так что мне нужно заполнить эти части, и кто-то может мне помочь, пожалуйста?

Вы можете проверить изображение по этой ссылке

Мой код:

    // 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)

1 Ответ

0 голосов
/ 04 января 2019

После 5 часов исследований, наконец, я нашел это расширение , и оно исправило мою проблему другим способом, это расширение помогает рисовать три четверти круга, поэтому я использовал его для рисования кругов, которые пустые со стороны углов прямоугольника.

А вот пример кода для использования:

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()
}
}

Результат изображения ссылка

...