2016-06-03 8 views
7

Zrobiłem okrągłą ścieżkę, środek ścieżki koła znajduje się pośrodku widoku. Następnie zrobiłem piłkę, która może poruszać się tylko po torze koła (przynajmniej taki, jak tego chcę): enter image description herePrzeciągnij piłkę nad ścieżką okręgu w Swift

Wykonałem funkcję, która przesuwa piłkę wszędzie tam, gdzie ją przeciągam (na ścieżce koła tylko), ale z jakiegoś powodu za każdym razem, kiedy go przeciągam, robi się szalony i nie porusza się tak, jak chcę, aby się poruszał.

To jest mój kod do tej pory:

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

Rozwiązaniem jest prawdopodobnie w matematyce zrobiłem w dragBall Func

+0

Eliko, mam problemy czyni tę pracę z autoLayout. Zobacz http://stackoverflow.com/questions/40885682/my-uiviews-muck-up-when-i-combine-uipangesturerecognizer-and-autolayout – Greg

Odpowiedz

6

Linia ta jest źle:

let angle = tan(angleY/angleX) 

Rejestracja chcesz obliczyć kąt ze współrzędnych, których potrzebujesz the "inverse tangent of two variables"

let angle = atan2(angleY, angleX) 
+0

Świetnie! To działa! Dziękuję :) Ale dlaczego potrzebuję odwrotnej stycznej, a nie regularnej? – Eliko

+1

@Eliko: Z grubsza mówiąc: 'slope = tan (kąt)', 'angle = atan (nachylenie)' –

+0

@MartinR to [ta odpowiedź] (http://math.stackexchange.com/a/1327368) wyjaśnia matematykę ? –

2

SWIFT 3 Zaktualizowany kod

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 
}