Chciałbym piłkę do śledzenia palcem jak przeciągnąć go wzdłuż trajektorii kołowej dla każdego dopuszczalnego orientacji urządzenia na iPhone lub iPad. Widoki wydają się być prawidłowo wycentrowane, gdy urządzenie jest obracane, ale kula nie pozostaje na obwodzie i wydaje się, że porusza się w dowolnym miejscu podczas przeciągania.mój UIViews syf-up kiedy łączę UIPanGestureRecognizer i autoLayout
EDIT
Martin R's answer wyświetla teraz to za konieczne. Moja jedyna dodatkowa zmiana kodu było usunięcie niepotrzebnych deklaracji var shapeLayer = CAShapeLayer()
matematyki w this example ma sens dopóki nie próbowałem ograniczać zarówno piłki i trajektorię do centrum widoku i dodanie centrum piłkę na współrzędne jako przesunięcia w czasie wykonywania. Poszłam za these recommendations on how to constrain a view.
Są trzy rzeczy, których nie rozumiem.
pierwsze, obliczanie obwodu okręgu jest z dwóch zmiennych trackRadius
i kąt theta
i korzystania sin
i cos
o theta
znaleźć x
i y
współrzędne nie umieści piłkę w dobrym położeniu.
Po drugie, korzystając atan
znaleźć kąt theta
pomiędzy centrum i punktu widzenia dotknął, a przy użyciu trackRadius
z theta
aby znaleźć x
i y
współrzędne nie będzie miejsca lub przenieść piłkę do nowego miejsca wzdłuż obwodu.
Po trzecie, za każdym razem, gdy przeciągam piłkę, wiadomość w obszarze debugowania mówi, że Xcode is Unable to simultaneously satisfy constraints
, mimo że nie zgłoszono żadnych problemów z ograniczeniami przed jej przeciągnięciem.
Tutaj może występować więcej niż jeden problem. Mój mózg zaczyna boleć i byłbym wdzięczny, gdyby ktoś mógł wskazać, co zrobiłem źle.
Oto mój kod.
import UIKit
class ViewController: UIViewController {
override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return .all }
var shapeLayer = CAShapeLayer()
let track = ShapeView()
var ball = ShapeView()
var theta = CGFloat()
private let trackRadius: CGFloat = 125
private let ballRadius: CGFloat = 10
override func viewDidLoad() {
super.viewDidLoad()
createTrack()
createBall()
}
private func createTrack() {
track.translatesAutoresizingMaskIntoConstraints = false
track.shapeLayer.path = UIBezierPath(ovalIn: CGRect(x: -trackRadius, y: -trackRadius, width: 2 * trackRadius, height: 2 * trackRadius)).cgPath
track.shapeLayer.fillColor = UIColor.clear.cgColor
track.shapeLayer.strokeColor = UIColor.red.cgColor
view.addSubview(track)
track.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
track.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
}
private func createBall() {
let offset = placeBallOnCircumference()
drawBall()
constrainBall(offset: offset)
let touch = UIPanGestureRecognizer(target: self, action:#selector(dragBall(recognizer:)))
view.addGestureRecognizer(touch)
}
private func placeBallOnCircumference() -> CGPoint {
let theta: Double = 0 // at 0 radians
let x = CGFloat(cos(theta)) * trackRadius // find x and y coords on
let y = CGFloat(sin(theta)) * trackRadius // circle circumference
return CGPoint(x: x, y: y)
}
func dragBall(recognizer: UIPanGestureRecognizer) {
var offset = CGPoint()
let finger : CGPoint = recognizer.location(in: self.view)
theta = CGFloat(atan2(Double(finger.x), Double(finger.y))) // get angle from finger tip to centre
offset.x = CGFloat(cos(theta)) * trackRadius // use angle and radius to get x and
offset.y = CGFloat(sin(theta)) * trackRadius // y coords on circle circumference
drawBall()
constrainBall(offset: offset)
}
private func drawBall() {
ball.shapeLayer.path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 2 * ballRadius, height: 2 * ballRadius)).cgPath
ball.shapeLayer.fillColor = UIColor.cyan.cgColor
ball.shapeLayer.strokeColor = UIColor.black.cgColor
view.addSubview(ball)
}
private func constrainBall(offset: CGPoint) {
ball.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
ball.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: offset.x),
ball.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: offset.y),
ball.widthAnchor.constraint(equalToConstant: trackRadius),
ball.heightAnchor.constraint(equalToConstant: trackRadius)
])
}
}
po dobrze przespanej nocy, co za radość budzi się do tego! Przybiliście wszystko, co próbowałem, i uczyniłem kod Swift bardziej zrozumiałym w tym procesie. To musi być zaakceptowana odpowiedź. – Greg