Display a GPS location on a map in the application

,

I can see how to capture GPS locations in the app, but how do I display a captured GPS location on a map in the application?

If you just want to display the contents of a GPS location that was captured in the application, then you can do this by programmatically accessing and displaying any of the underlying values that form part of the set of GPS coordinates.

VIEW XML

<info-table>
  <row label="Latitude" value="{location.latitude}" />
  <row label="Longitude" value="{location.longitude}" />
  <row label="Horizontal Accuracy" value="{location.horizontal_accuracy}" />
</info-table>

<capture-coordinates bind="location" />

example contents of a set of GPS coordinates in JS:

{
  "latitude": -25.92593042155752,
  "longitude": 28.15002065192829,
  "altitude": 1570.0,
  "horizontal_accuracy": 10.0,
  "vertical_accuracy": null,
  "timestamp": "2013-10-17T07:25:21Z"
}


However, If you want to display GPS coordinates on a MAP you will need to use an external map service like Google Maps, MapBox or MapQuest.

You can do this by displaying a static HTML file using the html component, or by dynamically updating and serving an HTML file using CloudCode and custom web tasks.

PS. It is also possible to do this dynamically in the application JS using HTML Bridge and the html component, but this is fairly complicated and is only useful if the map is required offline.

For now let's only look at the first two options.


STATIC HTML EXAMPLE

This example will display two markers on a map using a static HTML file that was added to the application's assets. It uses a mapbox JS library to render the map and the markers. It will require a MapBox API token to work

HTML FILE

<!DOCTYPE html>
<html>

  <head>
    <meta charset=utf-8 />
    <title></title>
    <script src='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.js'></script>
    <link href='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.css' rel='stylesheet' />
    <style>
        body {
            margin: 0;
            padding: 0;
            height: 800px;
        }

        .map {
            position: absolute;
            top: 0;
            bottom: 0;
            width: 100%;
            height: 800px
        }
    </style>
  </head>
  <body>
    <div id='map-popups' class='map'> </div>
    <script>
      L.mapbox.accessToken = ''; //  <<<<====== INSERT MAPBOX API TOKEN HERE ======>>>>
      L.mapbox.config.FORCE_HTTPS = true;
      var mapPopups = L.mapbox.map('map-popups', 'mapbox.light')
        .setView([38.8, -95], 5);
      var myLayer = L.mapbox.featureLayer().addTo(mapPopups);

      var geojson = [
        {
          type: 'Feature',
          geometry: {
            type: 'Point',
            coordinates: [-122.413682, 37.775408]
          },
          properties: {
            title: 'NOV - Casper [Rover]',
            description: 'SN: EZY13209; Next Cal: 2007-09-13',
            'marker-color': '#d81e05',
            'marker-size': 'medium',
            'marker-symbol': 'airport'
          } 
        },
        {
          type: 'Feature',
          geometry: {
            type: 'Point',
            coordinates: [-77.031952,  38.913184]
          },
          properties: {
            title: 'Pathfinder - Broussard [Grunter]',
            description: 'SN: NPU37555; Next Cal: 2009-01-15',
            'marker-color': '#9a2979',
            'marker-size': 'medium',
            'marker-symbol': 'monument'
          } 
        }
      ];
      myLayer.setGeoJSON(geojson);
    </script>
  </body>
</html>

VIEW XML

<html src="html/maps-example.html" show-fullscreen-button="true"/>


DYNAMIC HTML EXAMPLE

This example will display a map that is being served from a CloudCode webtask (called view_map) on a specific URL with several map markers populated from data in the DB. It uses a mapbox JS library to render the map and the markers, and a handlebars template to generate the HTML. It to will require a MapBox API token to work.

CLOUDCODE TASK JS

import handlebars from 'handlebars';

// This must be defined, and should return either access.authorized() or access.unauthorized()
export async function authenticate({request, access}) {
    return access.authorized();
}

// HTTP GET request
export async function get({params, request, response, authContext}) {
    // Handle the request here

    let mapMarkers = await DB.map_marker.all().toArray();
    let geoJSON = mapMarkers.map(function (marker) {
        return {
            type: 'Feature',
            geometry: {
                type: 'Point',
                coordinates: [marker.coordinates_lat, marker.coordinates_lon]
            },
            properties: {
                title: marker.title,
                description: marker.description,
                'marker-color': marker.marker_color,
                'marker-size': 'medium',
                'marker-symbol': marker.marker_symbol
            } 
        };
    });


    let mapPage = handlebars.compile(`
        <!DOCTYPE html>
        <html>

          <head>
            <meta charset=utf-8 />
            <title></title>
            <script src='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.js'></script>
            <link href='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.css' rel='stylesheet' />
            <style>
                body {
                    margin: 0;
                    padding: 0;
                    height: 800px;
                }

                .map {
                    position: absolute;
                    top: 0;
                    bottom: 0;
                    width: 100%;
                    height: 800px
                }
            </style>
          </head>
          <body>
            <div id='map-popups' class='map'> </div>
            <script>
              L.mapbox.accessToken = ''; //  <<<<====== INSERT MAPBOX API TOKEN HERE ======>>>>
              L.mapbox.config.FORCE_HTTPS = true;
              var mapPopups = L.mapbox.map('map-popups', 'mapbox.light')
                .setView([38.8, -95], 5);
              var myLayer = L.mapbox.featureLayer().addTo(mapPopups);

              var geojson = {{{mapMarkers}}}
              myLayer.setGeoJSON(geojson);
            </script>
          </body>
        </html>      
`);


    let data = {mapMarkers: JSON.stringify(geoJSON)};
    let html = mapPage(data);

    response.contentType('text/html');

    return html;
}

VIEW XML

<html src="https://{some_url}.poweredbyjourney.com/view_map" show-fullscreen-button="true"/>
1 Like

A correction/update:

The geoJSON object, under geometry.coordinates, must be [longitude, latitude] and not latitude first (as is the assumed standard)

Also, the traditional Mapbox.js is out of development now so it would be useful to use Mapbox GL syntax instead:

1 Like

This post is basically deprecated now since we have enhanced our coordinates components, for both capturing and displaying coordinates on a map.

Please see docs for standard JourneyApps components

That’s fantastic. Any suggestion for converting addresses to coordinates?

Hey @jwyrick

That is possible with most Maps APIs (Google Maps, MapBox, etc.) and is called “geocoding” or “address geocoding” or “forward geocoding”, but it is typically a paid service.

MapBox
Google Maps