Eliko - 1 year ago 58

Swift Question

I made a circle Path, the center of the circle path is in the middle of the view. Then, I made a ball that can move only on the circle path (at least this is what I want it to be):

I made a function that move the ball wherever I drag him (on the circle path only), but for some reason whenever I drag it, it gets crazy and doesn't move as I want it to move.

This is my code so far:

`class ViewController: UIViewController {`

var midViewX = CGFloat()

var midViewY = CGFloat()

var circlePath2 = UIBezierPath()

var shapeLayer2 = CAShapeLayer()

override func viewDidLoad() {

super.viewDidLoad()

midViewX = view.frame.midX

midViewY = view.frame.midY

// Do any additional setup after loading the view, typically from a nib.

let circlePath = UIBezierPath(arcCenter: CGPoint(x: midViewX,y: midViewY), radius: CGFloat(100), startAngle: CGFloat(0), endAngle:CGFloat(M_PI * 2), clockwise: true)

let shapeLayer = CAShapeLayer()

shapeLayer.path = circlePath.CGPath

shapeLayer.fillColor = UIColor.clearColor().CGColor

shapeLayer.strokeColor = UIColor.redColor().CGColor

shapeLayer.lineWidth = 3.0

view.layer.addSublayer(shapeLayer)

var angleEarth: Double = 180

var angleEarthAfterCalculate: CGFloat = CGFloat(angleEarth*M_PI/180) - CGFloat(M_PI/2)

var earthX = midViewX + cos(angleEarthAfterCalculate)*100

var earthY = midViewY + sin(angleEarthAfterCalculate)*100

circlePath2 = UIBezierPath(arcCenter: CGPoint(x: earthX,y: earthY), radius: CGFloat(10), startAngle: CGFloat(0), endAngle:CGFloat(M_PI * 2), clockwise: true)

shapeLayer2.path = circlePath2.CGPath

shapeLayer2.fillColor = UIColor.blueColor().CGColor

shapeLayer2.strokeColor = UIColor.clearColor().CGColor

shapeLayer2.lineWidth = 7

view.layer.addSublayer(shapeLayer2)

let dragBall = UIPanGestureRecognizer(target: self, action:#selector(ViewController.dragBall(_:)))

view.addGestureRecognizer(dragBall)

}

@IBAction func dragBall(recognizer: UIPanGestureRecognizer) {

let point = recognizer.locationInView(self.view);

let earthX = Double(point.x)

let earthY = Double(point.y)

let midViewXDouble = Double(midViewX)

let midViewYDouble = Double(midViewY)

let angleX = (earthX - midViewXDouble)

let angleY = (earthY - midViewYDouble)

let angle = tan(angleY/angleX)

let earthX2 = midViewXDouble + cos(angle)*100

let earthY2 = midViewYDouble + sin(angle)*100

circlePath2 = UIBezierPath(arcCenter: CGPoint(x: earthX2,y: earthY2), radius: CGFloat(10), startAngle: CGFloat(0), endAngle:CGFloat(M_PI * 2), clockwise: true)

shapeLayer2.path = circlePath2.CGPath

}

}

The solution is probably in the math I made in the

Answer Source

This line is wrong:

```
let angle = tan(angleY/angleX)
```

Since you want to calculate the angle from the coordinates you need the "inverse tangent of two variables"

```
let angle = atan2(angleY, angleX)
```