Geocoding with HERE APIs and Vue.js

Geocoding with HERE APIs and Vue.js

Created:27 Feb 2020 20:06:39 , in  Web development

Geocoding with HERE API and Vue.js

Geocoding is a process of finding a geographic location of an object on the Earth's surface. The location is specified using two coordinates. One is latitude, the other longitude. Both are specified in degrees. Latitude's range is 90 to -90 degrees ( The Northern Pole,the Equator, and Southern pole have 90, 0 and - 90 degrees latitudes respectively.) Longitude values range between -180 and 180 degrees.

Geocoding practically

In practical terms, geocoding is done by specialized software. For the needs of an application described in this article I use Here Technologies geocoding service. Here is a short description how the application works.

When a user specifies name (/ address / postal code) of a place they want to know coordinates of, the data gets passed on to the geocoding service. If the place exists somewhere on the Earth, and is found, the application displays a clickable marker at the location on a map. A click on the marker triggers an alert box to show on the screen. The box contains place's name, its longitude, latitude and a postal code (a small extra bit of information). The map is scalable, clickable and moveable. So if multiple locations are marked on the map, which is surprisingly common, all of them are easily reachable.

Live geocoder described in this article.

The logic of the application is encapsulated in a Vue.js component.The component is saved in hereGeocoding.js file and attached to a HTML file with the following markup:


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="initial-scale=1.0, width=device-width" />
  <title>Here Maps geocoding</title>
  <link rel="stylesheet" type="text/css" href="https://js.api.here.com/v3/3.1/mapsjs-ui.css" />
  <!-- Here Maps libraries -->
  <script src="https://js.api.here.com/v3/3.1/mapsjs-core.js" type="text/javascript" charset="utf-8"></script>
  <script src="https://js.api.here.com/v3/3.1/mapsjs-service.js" type="text/javascript" charset="utf-8"></script>
  <script src="https://js.api.here.com/v3/3.1/mapsjs-mapevents.js" type="text/javascript" charset="utf-8"></script>
  <script src="https://js.api.here.com/v3/3.1/mapsjs-ui.js" type="text/javascript" charset="utf-8"></script>

  <!-- Vue.js -->
 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

</head>
<body>

  <div id="hereGeocoding">
    <hereGeocoder v-bind:apk="'ENTER YOUR MAPS API KEY HERE'" v-bind:map-container="'hereMap'" v-bind:map-width="640" v-bind:map-height="480"></hereGeocoder>
  </div>

  <script src="hereGeocoding.js"></script>
</body>
</html> 

As can be seen, the HEAD tag is quiet JavaScript heavy. The libraries included in it are needed to display a fully functional map and and geocoding service.

One important fact, which is worth noting at this point is, that for an application like this to work, you need an API key (take another look at the HTML above). You can get your key by creating an account on Here Technologies website. API key is used to identify how many requests to the company's maps services you have made. First 250 000 transactions per month are free of charge, so there is more than enough room to play with various APIs the company has on offer.

Heregeocoder component

Now, let's look at the Vue.js component called 'heregeocoder" found in hereGeocoding.js file.

/**
 * Heregeocoder - Vue.js component for geocoding and interactive map rendering 
 * Author: S.Wojnowski
 * Licence: GNU
 */ 

Vue.component('heregeocoder',{
  props : ['apk','mapContainer','mapWidth','mapHeight'],

  data:function(){
    return {
      // other means of accessing this object
      that : this,
      mapContainerStyles:{width:this.mapWidth+'px',height:this.mapHeight+'px',display:'block'},
      location:"",
      // error styling
      errorStyle : {color:'#800000'},
      error:"",
      // map related data
      // initial map center coordinates and zoom level
      latitude : 0, 
      longitude : 0,
      zoom : 1,
      platform : null,
      geocoder : null,
      map : null,
      markers:null
    }
  },

  methods:{
    mapSetup : function(evt){
      let that = this;

      // Instantiate a map and platform object:
      this.platform = new H.service.Platform({
       'apikey': that.apk,
      });

      let terrain = that.platform.createDefaultLayers();

      // create new map
      this.map = new H.Map(
        document.getElementById(that.mapContainer),
        terrain.raster.normal.map,
        {
          zoom: that.zoom,
          center: { lat: that.latitude, lng: that.longitude }
        }
     );

     // add events to the map
     let mapEvents = new H.mapevents.MapEvents(this.map);

     // make the map reactive to resizing, tapping etc.
     new H.mapevents.Behavior(mapEvents);

     // add UI to the map
     H.ui.UI.createDefault(this.map, terrain);
   
     // create a marker group
     this.markers = new H.map.Group();
     this.map.addObject(this.markers);

     // get geocoder going
     this.geocoder = that.platform.getGeocodingService();
    },

    lookup : function(evt){ 
      let that = this;

      // remove error if any found before
      this.text = "";

      // remove previous markers are empty
      this.markers.removeAll();   

      let geocodingParams = {
        searchText: that.location
      };
    
      // geocoder response callback
      let onResult = function(result) {
        
        // clear errors
        that.error = "";

        let locations = result.Response.View[0].Result,position,marker;

        if(locations.length > 0){
          // Add a marker for each location found
          for (i = 0;  i < locations.length; i++) {

            let label = locations[i].Location.Address.Label;
            let postalCode = locations[i].Location.Address.PostalCode;
            let position = {
              lat: locations[i].Location.DisplayPosition.Latitude,
              lng: locations[i].Location.DisplayPosition.Longitude
            };

            let marker = new H.map.Marker(position);
            marker.setData('position',position)
            marker.addEventListener('tap',function(evt){

              let locationData = "";
              locationData += 'Location: ' +label+ "\n";
              locationData += 'Latitude: ' +position.lat+ ',Longitude: '+position.lng+"\n" 

              if(postalCode){
                locationData += 'Postal Code: '+postalCode;
              }

              alert(locationData);

            });
            
            // prepare markers
            marker.addOnDisposeCallback(function(evt){
              this.dispose();
            })
            that.markers.addObject(marker);
            that.map.setCenter(position,true);
          }
        }
      }

      this.geocoder.geocode(geocodingParams, onResult, function(e) {
        that.error="Input parameter validation failed. Missing mandatory parameters (at least one of: country, state, county, city, district, street, housenumber, postalCode or searchtext).";
      });
    }
  },

  // setup initial map view
  mounted:function(){
    this.mapSetup();
  },

  // basic geocoder template
  template:'<div> \
    <div v-bind:id="mapContainer" v-bind:style="mapContainerStyles"> \
    </div> \
    <div id ="mapControls"> \
      <p v-bind:style="errorStyle">{{error}}</p> \
      <p><input type="text" v-model:value="location" /> \
      <button v-on:click="lookup">look up</button> \
      </p> \
    </div> \
  </div>'
});

new Vue({
   el: '#hereGeocoding'
});

Whole map initialization code is specified in mapSetup method, which is hooked to "mounted" of Vue.js application. The most important properties of the map, like its dimensions and the API key for service are specified in the HTML part of the application, then collected by Vue.js component and assigned to values with the same names in its props property array. The rest of the code is responsible for fetching coordinates of user chosen place, creating interactive markers and displaying them on an interactive map. Nice and short.

Conclusion

Coordinates of a place on the Earth can be found using quiet a few different services. Usually, the obvious choice is Google's geocoding service. However, I chose to use a less known one provided by Here Technologies. They company offers a well designed product API, reasonable terms and conditions of use, decent documentation and extra examples of service integration on their blog. The whole maps and geocoding API is accessible using JavaScript, so it integrates really easily with a fronted frameworks like Vue.js.

I hope you have found the article informative and interesting.

Last but not least, I'm not in any way associated with Here Technologies, just happen to like their services.

This post was updated on 28 Feb 2020 02:03:13

Tags:  JavaScript ,  vue.js 


Author, Copyright and citation

Author

Sylwester Wojnowski

Author of the above article, Sylwester Wojnowski, enjoys sWWW writing computer code in PHP, JavaScript and BASH, and some other things he wrote more on on the About page of this website.

Copyrights

©Copyright, 2020 Sylwester Wojnowski. This article may not be reproduced or published as a whole or in parts without permission from the author. If you share it, please give author credit and do not remove embedded links.

Computer code, if present in the article, is excluded from the above and licensed under GPLv3.

Citation

Cite this article as:

Wojnowski, Sylwester. "Geocoding with HERE APIs and Vue.js." From sWWW - Code For The Web . https://wojnowski.net.pl//main/index/geocoding-with-here-apis-and-vuejs

Add Comment

Allowed BB Code - style tags: [b][/b], [i][/i], [code=text][/code],[code=javascript][/code],[code=php][/code],[code=bash][/code],[code=css][/code],[code=html][/code]


I constent to processing my data given through this form for purposes of a reply by the administrator of this website.

Recent Comments

Nobody has commented on this post yet. Be first!