在Swift中将球拖过圆圈path

我做了一个圆形path,圆形path的中心位于视图的中间。 然后,我做了一个只能在圆形path上移动的球(至less这是我想要的): 在这里输入图像说明

我做了一个移动球的function,只要我拖动它(仅在圆形path上),但由于某种原因,每当我拖动它时,它就会变得疯狂,并且不会随着我的移动而移动。

这是我的代码到目前为止:

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 } } 

解决scheme可能是我在dragBall Func中做的math

这一行是错误的:

  let angle = tan(angleY/angleX) 

既然你想从坐标计算angular度,你需要“两个variables的反正切”

  let angle = atan2(angleY, angleX) 

SWIFT 3更新了代码

 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.clear.cgColor shapeLayer.strokeColor = UIColor.red.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.blue.cgColor shapeLayer2.strokeColor = UIColor.clear.cgColor shapeLayer2.lineWidth = 7 view.layer.addSublayer(shapeLayer2) let dragBall = UIPanGestureRecognizer(target: self, action:#selector(dragBall(recognizer:))) view.addGestureRecognizer(dragBall) } func dragBall(recognizer: UIPanGestureRecognizer) { let point = recognizer.location(in: 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 angle = atan2(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 }