jueves, 5 de junio de 2014

Plugin device-orientation (brújula)

El nombre lo dice casi todo. Este plugin Phonegap/Cordova sirve para saber hacia dónde apunta el dispositivo, accediendo a la brújula. La brújula del dispositivo obtiene la dirección a la que apunta el mismo, normalmente, desde la parte superior, y está expresada en grados, desde 0 a 359'99 donde el 0 es el norte.

Plataformas soportadas

Este plugin está soportado por todos los sistemas más usados, por lo que implementarlo nos garantiza prácticamente 0 problemas de compatibilidad. Aquí el listado de los mismos:

  • Amazon Fire OS
  • Android
  • BlackBerry 10
  • Firefox OS
  • iOS
  • Tizen
  • Windows Phone 7 y 8
  • Windows 8

Instalación

Basta con escribir en consola, dentro de la carpeta del proyecto lo siguiente:
cordova plugin add org.apache.cordova.device-orientation

Y ya podremos hacer uso de los métodos de la API device-orientation.

Métodos

Son los siguientes, y podemos observar bastantes similitudes en su comportamiento respecto a los métodos de otras API como la del acelerómetro o la geolocalización.

  • navigator.compass.getCurrentHeading(onSuccess, onError);
  • navigator.compass.watchHeading(onSuccess, onError, [compassOptions]);
  • navigator.compass.clearWatch(watchID);
La explicación del funcionamiento de estos métodos es similar a la de los métodos análogos de otros plugins ya explicados, con la diferencia de que a las funciones callback onSuccess y onError se les envían otros objetos como parámetros. El objeto enviado a la función onSuccess es el llamado CompassHeading. Y a la función onError se le pasa el objeto CompassError. Por ejemplo, en el caso del acelerómetro, recordemos que a la función onSuccess(o como quisiéramos llamarla) se le pasaba el objeto Acceleration. Por lo demás, el funcionamiento es muy parecido. Con getCurrentHeading obtenemos la dirección a la que apunta el dispositivo en un momento determinado, con watchHeading realizamos un muestreo que referenciamos en una variable(en explicaciones anteriores la habíamos llamado watchID), y clearWatch sirve para detener ese muestreo.
También disponemos de un objeto de opciones, que podemos pasar de forma optativa, y contendrá la configuración con la que realizaremos el muestreo. Los valores que puede contener el objeto compassOptions son frequency y filter. Frequency determina el valor en milisegundos en el que haremos el muestreo de datos. Si además incluimos la opción filter, frequency es ignorado. Filter indica el valor mínimo en grados requerido para realizar una nueva llamada a la función onSuccess. No recomiendo incluir filter, porque no está soportado por muchos de los principales sistemas(Android, Windows Phone 7 y 8, entre otros).

Objetos

Como hemos mencionado antes, el objeto CompassHeading es pasado como parámetro a la función onSuccess cuando se obtienen datos de forma satisfactoria. Podemos acceder a sus siguientes propiedades:

  • magneticHeading: Valor numérico expresado en grados, que varía entre 0 y 359'99 y que indica hacia adónde apunta el dispositivo en el momento que se obtiene.
  • trueHeading: Igual que magneticHeading, pero relativo al polo Norte geográfico. Un valor negativo indica que no se puede determinar este valor.
  • headingAccuracy: Desviación en grados que puede haber entre los datos obtenidos y la dirección real a la que apunta el dispositivo.
  • timestamp: Tiempo en milisegundos en el que se tomó la muestra de datos.
No recomiento usar trueHeading y headindAccuracy por problemas documentados de compatibilidades.

El otro objeto del que podemos hacer uso es CompassError, que se pasa como parámetro a la función callback onError cuando llamamos a getCurrentHeading o watchHeading. Tiene la propiedad code, que puede valer, según el error:
  • CompassError.COMPASS_INTERNAL_ERR
  • CompassError.COMPASS_NOT_SUPPORTED
La explicación es bastante sencilla, o bien ha habido error al tomar los datos, o el dispositivo no dispone de brújula.


Ejemplo práctico

Vamos a implementar una brújula visual. ¿Cómo lo haremos? Mostraremos por pantalla una imagen cuya parte superior girará tantos grados como nos indique la propiedad magneticHeading del objeto CompassHeading, gracias a javascript y CSS. Una vez sabemos qué queremos y cómo implementarlo con las herramientas de las que disponemos, vamos a ello.

Partiremos del esqueleto que ya teníamos listo.
Por supuesto, podemos editar algunas opciones en el config.xml:

La imagen la guardaremos en www/img, yo he usado la siguiente imagen tomada de openclipart.org:
http://openclipart.org/image/300px/svg_to_png/188726/Compass_Rose_Arvin61r58.png




Una vez incluída en la carpeta de imágenes del proyecto, completamos el body del index.html tal que así:
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="format-detection" content="telephone=no" />
        <!-- WARNING: for iOS 7, remove the width=device-width and height=device-height attributes. See https://issues.apache.org/jira/browse/CB-4323 -->
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
        <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
        <link rel="stylesheet" type="text/css" href="css/index.css" />
        <title>Proyecto Phonegap</title>
    </head>
    <body>
        <div class="container">
            <h1 class="text-center">Brújula Phonegap</h1>
            <div class="row well text-center">
                <img img="brujula" src="img/brujula.png" alt="">
            </div>
        </div>
        
        <script type="text/javascript" charset="utf-8" src="cordova.js"></script>
        <script type="text/javascript" src="./js/jquery-1.11.0.min.js"></script>
        <script type="text/javascript" src="./js/bootstrap.min.js"></script>
        <script type="text/javascript" src="./js/fastclick.js"></script>
        <script type="text/javascript" src="./js/index.js"></script>
        <script type="text/javascript">
            window.addEventListener('load', function() {
                new FastClick(document.body);
            }, false);
            app.initialize();
        </script>
    </body>
</html>

Como vemos, sólo hemos añadido la etiqueta img cuya fuente es la imagen elegida, y mediante javascript le aplicaremos CSS con el giro que determine la brújula del dispositivo. Así queda el index.js:

var app = {
    // Application Constructor
    initialize: function() {
        this.bindEvents();
    },
    // Bind Event Listeners
    //
    // Bind any events that are required on startup. Common events are:
    // 'load', 'deviceready', 'offline', and 'online'.
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    // deviceready Event Handler
    //
    // The scope of 'this' is the event. In order to call the 'receivedEvent'
    // function, we must explicity call 'app.receivedEvent(...);'
    onDeviceReady: function() {
        app.receivedEvent('deviceready');
    },
    // Update DOM on a Received Event
    receivedEvent: function(id) {
        //tomaremos el muestreo de datos cada segundo (1000 ms)
        watchID = navigator.compass.watchHeading(onSuccess, onError, {frequency: 1000});

        //función onSuccess que aplica CSS a la imagen de la brújula del html
        function onSuccess(heading){
            //guardo los datos obtenidos del objeto CompassHeading
            var orientacion = 360-heading.magneticHeading;
            //aplico con jquery una rotación que depende de la variable orientacion
            $("#brujula").css('-webkit-transform','rotate(' + orientacion + 'deg)');
        }
        //funcion onError que tiene el objeto CompassError pasado como parámetro
        function onError(compassError) {
            //me limito a informar del error
            alert('Error: ' + compassError.code);
        }
    }
};


Como en ejemplos anteriores, usamos cosas propias de Phonegap una vez que se ha capturado el evento deviceready. En este caso, como ya hemos explicado, la magia está en rotar la imagen de la brújula con la línea $("#brujula").css('-webkit-transform','rotate(' + orientacion + 'deg)');
El muestreo se actualiza cada 1000 milisegundos, como bien expresa la opción frequency, pero se puede cambiar al gusto.

Antes de compilar, importante, instalar el plugin en nuestro proyecto, que luego vienen los llantos.

Y finalmente compilamos en local o en la nube y testeamos el funcionamiento del programa. Yo he optado por compilar en local con la orden phonegap build android, y copiar el fichero HelloWorld-debug-unaligned.apk de la carpeta platforms/android/ant-build en el teléfono directamente.

Imagen de la aplicación en ejecución:

No hay comentarios:

Publicar un comentario