Search code examples
swiftsprite-kituibezierpath

Swift: creating quarter circle with SKCropNode not working


The code below fails to generate a quarter circle. However, if you change the end angle to .pi, the code generates a semi-circle as expected.

Why does it fail for quarter circles?

    // Create circle
    let circleSize = CGSize(width: width, height: width)
    let circle = SKSpriteNode(texture: SKTexture(imageNamed: "Dot.png"), color: color, size: circleSize)
    circle.colorBlendFactor = 1.0

    // Add circle to crop node
    let cropNode = SKCropNode()
    cropNode.addChild(circle)

    // Set crop node mask
    let bezierPath = UIBezierPath(arcCenter: CGPoint(x: 0, y: 0), radius: width/2, startAngle: 0, endAngle: .pi/2, clockwise: true)
    let maskNode = SKShapeNode(path: bezierPath.cgPath)
    maskNode.isAntialiased = false
    maskNode.lineWidth = 0
    maskNode.fillColor = color
    cropNode.maskNode = maskNode

Dot.png (image is white so click below to download):

Dot.png below (white circle so click on space below)


Solution

  • The problem is that you are only drawing the arc, and the UIBezierPath closes the path by drawing a line back to the start. When you draw a semicircle, that works because the line drawn is the diameter of the circle.

    In the case of a quarter circle, you end up with a chord that connects the two endpoints, but that doesn't give you the desired result.

    To fix this, draw a line to the center of the circle (0, 0) after you draw the arc. Then when the path is closed, it will draw the other radius back to the starting point of the arc.

    New bezierPath code:

    let bezierPath = UIBezierPath(arcCenter: CGPoint(x: 0, y: 0), radius: width/2, startAngle: 0, endAngle: .pi/2, clockwise: true)
    bezierPath.addLine(to: CGPoint(x: 0, y: 0))