zennox
zennox

Reputation: 644

Swift: UIBezierPath bezierPathByReversingPath() Issues

I am using bezierPathByReversingPath() trying to make an animating circle. I finally found a method that will work, but I am getting this bar across the circle that is not being "deleted".

The Code:

@IBDesignable class circle: UIView {

    override func drawRect(rect: CGRect) {
        let center = CGPoint(x:bounds.width/2, y: bounds.height/2)

        let circlePath : UIBezierPath = UIBezierPath(arcCenter: center, radius:
            CGFloat(250), startAngle: CGFloat(0), endAngle: CGFloat(360), clockwise: true)
        let circlePath2 : UIBezierPath = UIBezierPath(arcCenter: center, radius:
            CGFloat(200), startAngle: CGFloat(0), endAngle: CGFloat(360), clockwise: true)

        circlePath.appendPath(circlePath2.bezierPathByReversingPath())
        circlePath.fill() //appendPath(circlePath.bezierPathByReversingPath())    
    }
}

The Picture

enter image description here

P.S. If you want an example of what I am doing, it is a win/lose animation in the iOS game "Dulp".

Upvotes: 2

Views: 675

Answers (2)

user887210
user887210

Reputation:

First of all, the angles are in radians - not degrees. So your circles are going around 30 or so times and not ending up where they started. That's what gives you the bar.

Secondly, you can just stroke one circle instead of creating two and filling them:

@IBDesignable class Circle: UIView {
  override func drawRect(rect: CGRect) {
    let center = CGPoint(x:bounds.width/2, y: bounds.height/2)

    let circlePath : UIBezierPath = UIBezierPath(arcCenter: center, radius:
      CGFloat(225), startAngle: CGFloat(0), endAngle: CGFloat(2*M_PI), clockwise: true)
    circlePath.lineWidth = 50
    circlePath.stroke()
  }
}

Upvotes: 1

Unheilig
Unheilig

Reputation: 16302

It is because UIBezierPath(arcCenter: center, radius: CGFloat(250), startAngle: CGFloat(0), endAngle: CGFloat(360), clockwise: true) takes radians, not degrees, as you specify here.

Thus, one would need to supply the arguments in radians.

I created a simple function that converts from degrees to radians; the result turned out fine.

Here is the function:

func degreesToRadians(degree : Int) -> CGFloat
{
    return CGFloat(degree) * CGFloat(M_PI) / 180.0
}

Usage:

let circlePath : UIBezierPath = UIBezierPath(arcCenter: center, radius: 250.0, startAngle: self.degreesToRadians(0), endAngle:    
                                             self.degreesToRadians(360), clockwise: true)

let circlePath2 : UIBezierPath = UIBezierPath(arcCenter: center, radius: 200.0, startAngle: self.degreesToRadians(0), endAngle:        
                                              self.degreesToRadians(360), clockwise: true)

Or one could create a protocol extension:

extension Double
{
    var degreesToRad : CGFloat
    {
        return CGFloat(self) * CGFloat(M_PI) / 180.0
    }
}

Usage:

let circlePath : UIBezierPath = UIBezierPath(arcCenter: center, radius: 250.0, startAngle: 0.0.degreesToRad , endAngle: 360.0.degreesToRad, clockwise: true)

let circlePath2 : UIBezierPath = UIBezierPath(arcCenter: center, radius: 200.0, startAngle: 0.0.degreesToRad, endAngle: 360.0.degreesToRad, clockwise: true)

Upvotes: 1

Related Questions