I am making an App which able to make panorama video in landscape. In landscape, it supports two directions: left to right and bottom to top.
So I want to move an arrow from left to right when user move the phone from left to right or rotate to right. Also want to move the arrow bottom to top when move the device vertically upwards. In native iPhone camera app with panorama option, there we can see the correct simulation,
My questions are 1) how do I know user is moving the phone from left to right or right to left. Because like iPhone panorama, I want to stop recording when user move back.
Also 2) how do I know user is moving the phone vertically upwards
Added : Nov 10, 2017: I did see an app named Spincle in AppStore. It is moving the arrow when rotate the device from left to right to take 360 image. I just managed to achieve this using pitch and roll (see the below code). But this will not work if we stand device to floor or roof a bit.
import UIKit
import CoreMotion
class ViewController: UIViewController {
private let motionManager = CMMotionManager()
let arrowView = UIView()
func startMotion() {
var initialAttitude: CMAttitude?
motionManager.deviceMotionUpdateInterval = 1
let queue = OperationQueue.current!
let statusBarOrientation = UIApplication.shared.statusBarOrientation
motionManager.startDeviceMotionUpdates(using: CMAttitudeReferenceFrame.xArbitraryZVertical, to: queue) { (motiondata, err) in
guard let data = motiondata else { return }
if initialAttitude == nil {
initialAttitude = data.attitude
} else {
let attitude = data.attitude
// translate the attitude
attitude.multiply(byInverseOf: initialAttitude!)
// calculate pitch and roll of the change from our initial attitude
let pitch = self.radiansToDegrees(attitude.pitch)
let roll = self.radiansToDegrees(attitude.roll)
print("\nroll = \(roll), pitch = \(pitch), yaw = \(self.radiansToDegrees(attitude.yaw))")
print("x = \(data.userAcceleration.x), y = \(data.userAcceleration.y), z = \(data.userAcceleration.z)")
DispatchQueue.main.async {
var rect = self.arrowView.frame
var addXPixel = self.view.frame.size.width/45
var addYPixel = self.view.frame.size.height/45
if statusBarOrientation == .landscapeRight {
addXPixel *= -1
} else {
addYPixel *= -1
}
rect.origin.x = (CGFloat(pitch) * addXPixel)
rect.origin.y = (self.view.frame.size.height/2 - 20) + (CGFloat(roll) * addYPixel)
self.arrowView.frame = rect
}
}
}
}
func stopMotion() {
motionManager.stopDeviceMotionUpdates()
}
func radiansToDegrees(_ radian: Double) -> Float {
return Float(radian * 180.0/Double.pi)
}
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(arrowView)
arrowView.backgroundColor = UIColor.red
}
@IBAction func tappedButton() {
arrowView.frame = CGRect(x: 0, y: self.view.frame.size.height/2 - 20, width: 40, height: 40)
startMotion()
}
}
The issue is it will go left to right a bit and the arrow moving upwards or downwards
You can use CLLocationManager
to check the heading of your phone, and write your algorithm to determine the left-right / bottom-top movement by calculating CLHeading
's degrees.
- (void)locationManager:(CLLocationManager*)manager
didUpdateHeading:(CLHeading*)newHeading
https://developer.apple.com/documentation/corelocation/clheading
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With