Reputation: 4491
Hey~~ I am trying to draw a solid round dot with a rectangle handle on top of it. (backcolor: purple, forecolor: black)
However, the shapes are all correct, but when I am coloring it, there is a gap at the shape overlapping area, which cannot be filled with solid color.
How should I correct it? Thanks!
var shapeLayer: CAShapeLayer!
func draw() {
let path = UIBezierPath()
// draw a rectangle
path.move(to: CGPoint(x: 90, y: 0))
path.addLine(to: CGPoint(x: 90, y: 100))
path.addLine(to: CGPoint(x: 110, y: 100))
path.addLine(to: CGPoint(x: 110, y: 0))
path.addLine(to: CGPoint(x: 90, y: 0))
// draw a circle
path.move(to: CGPoint(x: 100, y: 100))
path.addArc(withCenter: CGPoint(x: 100, y: 100), radius: 50, startAngle: 0, endAngle: 2 * CGFloat.pi, clockwise: true)
// fill colors with purple and black
self.shapeLayer.path = path.cgPath
self.shapeLayer?.fillColor = foreColor.cgColor
self.backgroundColor = backColor
}
Upvotes: 1
Views: 1157
Reputation: 4491
Besides @vacawama 's answer, another approach I found out is that I can use a non-enclosed rectangle instead of a closed rectangle, the rect is opened in one side that was connecting with the circle:
let path = UIBezierPath()
// an open rectangle
path.move(to: CGPoint(x: 90, y: 52))
path.addLine(to: CGPoint(x: 90, y: 0))
path.addLine(to: CGPoint(x: 110, y: 0))
path.addLine(to: CGPoint(x: 110, y: 52))
// the same circle
path.append(UIBezierPath(ovalIn: CGRect(x: 50, y: 50, width: 100, height: 100)))
This works too, but it is really good to know about the "non-zero winding rule", so cool, thanks!
I am happy now :)
Upvotes: 0
Reputation: 154603
Draw your rectangle in the opposite direction:
// draw a rectangle
path.move(to: CGPoint(x: 90, y: 0))
path.addLine(to: CGPoint(x: 110, y: 0))
path.addLine(to: CGPoint(x: 110, y: 100))
path.addLine(to: CGPoint(x: 90, y: 100))
path.addLine(to: CGPoint(x: 90, y: 0))
The non-zero winding fill used by CoreGraphics uses the direction of the lines to determine inside/outside.
Alternatively, you can reverse the direction of your circle:
path.addArc(withCenter: CGPoint(x: 100, y: 100), radius: 50,
startAngle: 2 * CGFloat.pi, endAngle: 0, clockwise: false)
Upvotes: 2