Tracking Location

GPS sensor, mapové podklady, knižnica Leaflet

About

GPS sa stal neoddeliteľnou súčasťou (nie len) mobilných zariadení. Možnosti jeho využitie posúvajú aj bežné aplikácie na úplne inú úroveň. Či sa už jedná vyslovene o aplikácie priamo využívajúce GPS senzor (rozličné športové trackovacie aplikácie alebo navigácie) alebo zaujímavé využitia tohto senzora (napr. zvýšenie bezpečnosti).

V tomto cvičení sa teda pozrieme na možnosti práce s GPS senzorom a zobrazovanie mapových podkladov pomocou knižnice Leaflet.

Objectives

  • naučiť sa pracovať s GPS senzorom
  • zoznámiť sa s knižnicou Leaflet

Postup

New Project

V prvom kroku vytvoríme projekt aplikácie spolu s jej základnou konfiguráciou.

Úloha

Vytvorte si nový projekt s názvom Tracker, ktorý sa bude nachádzať v balíčku sk.tuke.smart.tracker.

Úloha

Do projektu pridajte platformy Android a Browser.

Úloha

Do projektu pridajte rozšírenia cordova-plugin-geolocation a cordova-plugin-dialogs.

Úloha

Upravte rozloženie aplikácie podľa nasledujúceho fragmentu elementu <body>.

<body>
    <div id="app">
        <div id="map"></div>
        <div id="location"></div>
        <button>Get Location</button>
    </div>

    <script src="cordova.js"></script>
    <script src="js/index.js"></script>
</body>

Vzhľad aplikácie definujte pomocou CSS štýlu, ktorého kostra môže vyzerať takto:

#app {
    text-align: center;
}

body {
    padding: 0;
    margin: 0;
}

html, body, #app, #map {
    height: 90%;
    width: 100vw;
}

Kód aplikácie v súbore index.js môže vyzerať zatiaľ takto:

var app = {
    initialize: function() {
        document.addEventListener(
            "deviceready",
            this.onDeviceReady.bind(this),
            false
        );
    },

    onDeviceReady: function() {}
};

app.initialize();

Rozloženie aplikácie si upravte podľa seba. Dôležitú sú len hodnoty atribútov id.

Úloha

Spustite vašu aplikáciu v prehliadači.

Ak ste postupovali podľa pokynov, mala by sa vám zobraziť aplikácia, v ktorej bude len jedno tlačidlo.

Kostra projektu Tracker

Retrieving Current Location

Aktuálnu polohu získame z objektu navigator.geolocation volaním metódy getCurrentPosition(). V tomto kroku teda zabezpečíme, aby sa po stlačení tlačidla zobrazila zemepisná šírka aj výška v bloku s názvom location.

Úloha

Ošetrite kliknutie na tlačidlo zavolaním metódy updateLocation() nad objektom aplikácie.

Úloha

Implementujte metódu updateLocation(), ktorá po zavolaní zobrazí aktuálnu hodnotu zemepisnej šírky a výšky v bloku s id location a v prípade problémov zobrazí chybu pomocou samostatného chybového dialógu.

Na tento účel použijeme volanie metódy navigator.geolocation.getCurrentPosition(). Táto funkcia vráti aktuálnu polohu zariadenia v parametri Position callback-u geolocationSuccess. V prípade, že dôjde k chybe, bude zavolaný callback geolocationError, ktorému bude odovzdaný objekt PositionError.

navigator.geolocation.getCurrentPosition(geolocationSuccess,
                                         [geolocationError],
                                         [geolocationOptions]);

Príklad použitia metódy môže vyzerať takto:

// onSuccess Callback
// This method accepts a Position object, which contains the
// current GPS coordinates
//
var onSuccess = function(position) {
    alert('Latitude: '          + position.coords.latitude          + '\n' +
          'Longitude: '         + position.coords.longitude         + '\n' +
          'Altitude: '          + position.coords.altitude          + '\n' +
          'Accuracy: '          + position.coords.accuracy          + '\n' +
          'Altitude Accuracy: ' + position.coords.altitudeAccuracy  + '\n' +
          'Heading: '           + position.coords.heading           + '\n' +
          'Speed: '             + position.coords.speed             + '\n' +
          'Timestamp: '         + position.timestamp                + '\n');
};

// onError Callback receives a PositionError object
//
function onError(error) {
    alert(`code: ${error.code}\nmessage: ${error.message}\n`);
}

navigator.geolocation.getCurrentPosition(onSuccess, onError);

Úloha

Overte svoju implementáciu.

Svoju implementáciu môžete overiť využitím rozšírenie Cordova Tools prostredia Visual Studio Code. Experimentujte s manuálnym nastaovaním polohy a jeho následným odčítaním v aplikácii.

Tracker: zobrazenie polohy po kliknutí na tlačidlo

Úloha

Rozšírte implementáciu tak, aby sa poloha zariadenia sama aktualizovala pri jej zmene.

Sledovanie zmeny polohy zabezpečíme volaním metódy navigator.geolocation.watchPosition(). V prípade, že dôjde k zmene polohy, dôjde k zavolaniu callback-u geolocationSuccess a v parametri Position bude odovzdaná nová poloha. V prípade vzniku chyby bude zavolaný callback geolocationError s parametrom PositionError.

var watchId = navigator.geolocation.watchPosition(geolocationSuccess,
                                                  [geolocationError],
                                                  [geolocationOptions]);

Príklad použitia:

// onSuccess Callback
//   This method accepts a `Position` object, which contains
//   the current GPS coordinates
//
function onSuccess(position) {
    var element = document.getElementById('geolocation');
    element.innerHTML = 'Latitude: '  + position.coords.latitude      + '<br />' +
                        'Longitude: ' + position.coords.longitude     + '<br />' +
                        '<hr />'      + element.innerHTML;
}

// onError Callback receives a PositionError object
//
function onError(error) {
    alert(`code: ${error.code}\nmessage: ${error.message}\n`);
}

// Options: throw an error if no update is received every 30 seconds.
//
var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { timeout: 30000 });

Úloha

Overte svoju implementáciu.

V prípade, že ste postupovali správne, pri akejkoľvek zmene sa výpis aktuálnej polohy zmení. Experimentovať môžete so Cordova Tools, kde môžete meniť aktuálnu polohu manuálne alebo si môžete nahrať súbor morning.travel.gpx, ktorý obsahuje priamo záznam z cestovania.

The Maps

Zatiaľ vieme zobrazovať len aktuálnu polohu, čo je dosť nuda. Správna navigácia, resp. mapová aplikácia vizualizuje aktuálnu polohu na mape.

V tomto prípade máme na výber hneď z niekoľkých mapových podkladov, ako napr. Google Maps, Bing Maps alebo OpenStreetMap. Kvôli licenčným podmienkam pre naše experimenty budeme používať mapové podklady z projektu OpenStreetMap.

Aj v prípade použitia podkladov z projektu OpenStreetMap máme k dispozícii niekoľko možností: Leaflet alebo OpenLayers 2. Pre naše experimentovanie použijeme Leaflet.

Pre rýchlosť implementácie budeme používať CDN verziu projektu. Pre offline použitie aplikácie je však nutné, aby boli všetky súbory súčasťou aplikácie!

Úloha

Pridajte do súboru index.html CSS štýly ako aj JavaScript-ové súbory projektu Leaflet.

Postupujte podľa pokynov uvedených na stránke projektu: pre použitie s CDN použite nasledovný kód:

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css"
  integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
  crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js"
  integrity="sha512-GffPMF3RvMeYyc1LWMHtK8EbPv0iNZ8/oTtHPx9/cc2ILxQ+u905qIwdpULaqDkyBKgOaB57QTMg7ztg8Jm2Og=="
  crossorigin=""></script>

Úloha

Ošetrite nežiadúce škálovanie stránky mobilného prehliadača a nastavte ho na jeho aktuálnu veľkosť.

To zabezpečíme vložením, resp. aktualizovaním nasledujúceho meta elementu v HTML dokumente:

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />

Úloha

V objekte aplikácie vytvorte premennú map, ktorú inicializujete pri ošetrení udalosti deviceready vytvorením objektu mapy.

onDeviceReady: function() {
    // ...
    this.map = L.map("map").fitWorld();
    L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
        attribution:
            'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'
    }).addTo(this.map);
    // ...
},

Po spustení by ste mali vidieť mapu sveta na obrazovke telefónu.

Tracker: mapa sveta

Úloha

Pri ošetrovaní zmeny polohy v metóde updateLocation() aktualizujte aj zobrazenie mapy.

app.map.locate({ setView: true, maxZoom: 16 });

Úloha

Overte svoju implementáciu.

Ak ste postupovali správne, uvidíte mapu okolia, v ktorom sa nachádzate.

Tracker: mapa okolia

Úloha

Pridajte do mapy marker, ktorý bude zobrazovať vašu aktuálnu polohu.

Marker je potrebné vykresliť na aktuálnu polohu. V prípade, že dôjde k aktualizácii mapy, nezabudnite marker aktualizovať tiež!

if (app.marker) {
    app.marker.remove();
}
app.marker = L.marker([lat, lon]).addTo(app.map);

Úloha

Overte svoju implementáciu.

Ak ste postupovali správne, uvidíte na mape svoju polohu.

Tracker: zobrazenie aktuálnej polohy s markerom

Úloha

Overte svoju implementáciu vypublikovaním aplikácie na mobilné zariadenie.