Saturday, November 18, 2017

CoreMotion - get left-right, bottom-up movement on iPhone in landscape

Leave a Comment

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 move the device from left to right without rotation.

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

1 Answers

Answers 1

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 Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment