简体   繁体   中英

Swift: UIBezierPath fill intersection of 2 paths

I'm working with 2 UIBezierPath to create a rectangle and a semicircle shape. It works fine but I am not able to fill the intersection with color.

在此处输入图片说明

That's my drawCircle and my addPaths functions:

private func drawCircle(selectedPosition: SelectionRangePosition, currentMonth: Bool) {
    circleView.layer.sublayers = nil

    let radius = contentView.bounds.height/2
    let arcCenter = CGPoint(x: ceil(contentView.bounds.width/2), y: ceil(contentView.bounds.height/2))
    let circlePath = UIBezierPath(arcCenter: arcCenter, radius: radius, startAngle: .pi/2, endAngle: .pi * 3/2, clockwise: selectedPosition == .left)

    let semiCircleLayerPath = UIBezierPath()
    let semiCircleLayer   = CAShapeLayer()
    semiCircleLayer.fillColor = UIColor.tealish.cgColor

    circleView.layer.addSublayer(semiCircleLayer)

    switch (selectedPosition, currentMonth) {
    case (.left, true):
        let rectanglePath = UIBezierPath(rect: CGRect(x: contentView.bounds.width / 2, y: 0, width: ceil(contentView.bounds.width / 2), height: contentView.bounds.height))
        addPaths(semiCircleLayerPath, rectanglePath, circlePath, semiCircleLayer)

    case (.middle, true):
        backgroundColor = .tealish

    case (.right, true):

    // Note: The + 10 is just to overlap the shapes and test if the filling works

        let rectanglePath = UIBezierPath(rect: CGRect(x: 0, y: 0, width: ceil(contentView.bounds.width / 2) + 10, height: contentView.bounds.height))
        addPaths(semiCircleLayerPath, rectanglePath, circlePath, semiCircleLayer)

    default:
        backgroundColor = .clear

    }
}

private func addPaths(_ semiCircleLayerPath: UIBezierPath, _ rectanglePath: UIBezierPath, _ circlePath: UIBezierPath, _ semiCircleLayer: CAShapeLayer) {
    semiCircleLayerPath.append(circlePath)
    semiCircleLayerPath.append(rectanglePath)

    semiCircleLayer.path = semiCircleLayerPath.cgPath
}

The problem is that the semicircle path and the rectangle path are being added in opposite directions. This is a function of the way the Cocoa API adds them, unfortunately; in your case, it means that the intersection has a "wrap count" of 0.

Fortunately, there is an easy fix: create separate paths for the semicircle and the rectangle. When fill them both individually, you should get your desired result.

Unfortunately, this will mean that you can't use layer drawing only: you will want to use the drawRect method to draw the background.

If your dates are separate UILabels, you can skip this rendering & path filling problem entirely by dropping a UIView as a child of the calendar, under the labels holding the dates; give it a background color & rounded corners (using layer.cornerRadius as usual). That'll take care of your rounded rect for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM