Device Orientation Helper Script


#1

Here is a script I’m using that uses the @ionic-native/device-motion plugin. Essentially the script will very easily return a value that states whether your device is in landscape or portrait orientation.

It’s important to note that this script is definitely not full proof. There are some known pitfalls for how it detects orientation, and it could definitely be better. For my purposes though it works well, and I thought it might help a few people out.

device-orientation-helper.ts

import {Injectable} from "@angular/core";
import {DeviceMotion, DeviceMotionAccelerationData} from "@ionic-native/device-motion";
import {Observable} from "rxjs/Observable";

export enum Orientations{ PORTRAIT, LANDSCAPE }

@Injectable()
export class DeviceOrientationHelper {

  private currentOrientation: Orientations;
  //private deviceObserver: Observer<Orientations>;
  constructor(private deviceMotion: DeviceMotion) {}

  public watchOrientationChange(frequency: number): Observable<Orientations>{
    return this.deviceMotion.watchAcceleration({frequency: frequency})
      .flatMap((acceleration: DeviceMotionAccelerationData) => { return this.setAccelerationToOrientationEnum(acceleration) });
  }

  private setAccelerationToOrientationEnum(acceleration: DeviceMotionAccelerationData): Observable<Orientations>{

    return Observable.create(observer => {
      //translate acceleration on x y axis to yaw
      let yaw = Math.atan(acceleration.y/acceleration.x) * (180 / Math.PI);
      let yawTranslated = (90 - yaw) + (Math.sign(yaw)*90);

      //Phone isn't face up / down & we only register phone position left <-> up <-> right
      if(Math.abs(acceleration.z) < 7 && acceleration.y > 0){
        if(yawTranslated <= 135 && yawTranslated >= 45){
          if(this.currentOrientation !== Orientations.PORTRAIT){
            this.currentOrientation = Orientations.PORTRAIT;
            observer.next(this.currentOrientation);
          }
        }else{
          if(this.currentOrientation !== Orientations.LANDSCAPE){
            this.currentOrientation = Orientations.LANDSCAPE;
            observer.next(this.currentOrientation);
          }
        }
      }
    });
  }
}

use

    this.deviceOrientationSubscriber = this.deviceOrientationHelper.watchOrientationChange(500).subscribe(
      (orientation: Orientations) => {
         //every 500 milliseconds (as set above) will return either PORTRAIT or LANDSCAPE
        console.log(orientation);
      }
    );