Ionic Maps Video

Ionic 2 & 3: How to Use Google Maps & Geolocation



·

Adding map functionality to a mobile application can be extremely useful, especially when we throw Geolocation into the mix. The nature of mobile devices are that they are mobile obviously, and maps are generally most useful to people when they are on the move. It also gives us an awesome opportunity to display information contextually to a user (e.g. other users of the app that are nearby).

I’ve already covered how to add Google Maps API to an Ionic application, but now I’m going to show you how to set up the Google Maps API in an Ionic 2 application.

UPDATE: For a more advanced implementation of Google Maps in Ionic 2, check out this tutorial.

Before we Get Started

Last updated for Ionic 3.7.1

Before you go through this tutorial, you should have at least a basic understanding of Ionic 2 concepts. You must also already have Ionic 2 set up on your machine.

If you’re not familiar with Ionic 2 already, I’d recommend reading my Ionic 2 Beginners Guide first to get up and running and understand the basic concepts. If you want a much more detailed guide for learning Ionic 2, then take a look at Building Mobile Apps with Ionic 2.

Setting up a new Ionic 2 Project

I’m just going to be running through the motions here and listing off the commands you’ll need to run and things you’ll need to do to get your project ready for building this application. I explained this process and gave a lot more background in my tutorial on building a todo application in Ionic 2, so I highly recommend checking that out if you’re unfamiliar with how an Ionic 2 project is structured.

To generate a new Ionic 2 project, we can run the following command:

ionic start ionic-maps blank --v2

Once the project has finished generating, make it your current directory:

cd ionic-maps

If you take a look at the files and folders that are generated by the Ionic CLI, you will see that under app there is a home folder. This contains the default home component, which is made up of both a TypeScript file (where the class definition is held) and a HTML file (where the template is defined). We will use this for creating our map.

1. Adding the Google Maps SDK to an Ionic 2 Application

The Google Maps JavaScript API can be embedded and used on any website for free (up to a reasonably generous limit). Since it can be embedded in websites, it can also be embedded in HTML5 mobile applications.

It’s worth noting that there is also native Google Maps SDKs for iOS and Android, which we can also make use of through the use of a PhoneGap plugin. Although I’ve never used it myself, the native SDK should have better performance.

The JavaScript API works very well on mobile though, and I’ve used it for all of my projects that have required map functionality so far. As long as you take a smart approach to rendering markers, which I’ve covered in a previous series for map integration in Ionic 1, the Javascript API on mobile is capable of handling maps with thousands of markers.

Add the JavaScript SDK

To make the JavaScript API available within our application we will need to include the library. You can do so by loading it in your src/index.html file.

Include the Google Maps API in your src/index.html file (above the cordova.js file):

  <script src="http://maps.google.com/maps/api/js?key=YOUR_API_KEY_HERE"></script>
  <script src="cordova.js"></script>

NOTE: It is also important that you generate an API key for Google Maps and add it to the query string for the <script> tag above (replace YOUR_API_KEY_HERE). To generate an API key, just go to this page and follow the instructions under Get an API key.

Load the Map

Now that the Google Maps Javascript API is available within our application, we can create and load a map. Let’s start by adding a map to the template for our map component

Modify home.html to reflect the following

<ion-header>
  <ion-navbar>
    <ion-title>
      Map
    </ion-title>
    <ion-buttons end>
      <button ion-button (click)="addMarker()"><ion-icon name="add"></ion-icon>Add Marker</button>
    </ion-buttons>  
  </ion-navbar>
</ion-header>

<ion-content>
  <div #map id="map"></div>  
</ion-content>

We’re providing a title of Map and a button in the end position (you may also use start instead). We add a click listener for this button which will trigger the addMarker() function which will soon be defined in our home.ts file when clicked. Then we simply create a placeholder <div> to act as a container for the map we will add shortly. By adding #map to the element, we will be able to grab a reference to it with ViewChild later.

Now we need to modify our class definition for the map component to take care of generating a new map, and adding it to that container we just created.

Modify home.ts to reflect the following

import { Component, ViewChild, ElementRef } from '@angular/core';
import { NavController } from 'ionic-angular';

declare var google;

@Component({
  selector: 'home-page',
  templateUrl: 'home.html'
})
export class HomePage {

  @ViewChild('map') mapElement: ElementRef;
  map: any;

  constructor(public navCtrl: NavController) {

  }

  ionViewDidLoad(){
    this.loadMap();
  }

  loadMap(){

    let latLng = new google.maps.LatLng(-34.9290, 138.6010);

    let mapOptions = {
      center: latLng,
      zoom: 15,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    }

    this.map = new google.maps.Map(this.mapElement.nativeElement, mapOptions);

  }
}

We have created a member variable to hold our map and we have also created a member variable that references the map element (the one we added #map to in the template). Also, notice that we have added declare var google; above the decorator, this is to prevent any warnings from TypeScript about the google object that the Google Maps SDK makes available to us. We use the ionViewLoaded function, which will run when the view is loaded, to call the loadMap function.

This function will handle creating a new map and loading it into our map div. We create a LatLng object, which is provided by the Google Maps API, to represent the location that we want to center the map on. For now I’ve set it to be my hometown of Adelaide, but in the next section we will use the Geolocation API to automatically set this to the users location.

Before creating our map, we create a mapOptions object which allows us to define some options for our map. Here we supply the center coordinates we just created, the initial zoom level, and the type of map we want (in this case we are using the road map style, but you could also use the satellite style for example).

Note that we are also keeping a reference to our map using this.map as we will need to refer to it elsewhere in this class.

Style the Map

All the code is in place to get our map working now, but if you take a look at it by running ionic serve you’ll just see a big blank screen. To get Google Maps to display correctly in an Ionic application, you need to add some styles first.

Add the following styles to your src/pages/home/home.scss file:

.ios, .md {

    home-page {

      .scroll {
        height: 100%
      }

      #map {
        width: 100%;
        height: 100%;
      }

    }

}

Now if you try to view your application you should actually be able to see the map.

2. Add the Geolocation plugin

The Geolocation API is the perfect companion for a maps application – maps deal with locations, and the Geolocation API allows you to retrieve a users location.

If you’re running this on a device, make sure to install the Geolocation plugin by running:

ionic plugin add cordova-plugin-geolocation

You will also need to install the Ionic Native package for this plugin with the following command:

npm install --save @ionic-native/geolocation

and add Geolocation as a provider in your src/app/app.module.ts file:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule, ErrorHandler } from '@angular/core';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { Geolocation } from '@ionic-native/geolocation';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';

@NgModule({
  declarations: [
    MyApp,
    HomePage
  ],
  imports: [
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    Geolocation,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}

Geolocation will also work directly through the browser though, as it is part of the HTML5 API. Let’s modify our src/pages/home/home.ts file to make use of Geolocation now.

Modify src/pages/home/home.ts to reflect the following:

import { Component, ViewChild, ElementRef } from '@angular/core';
import { NavController } from 'ionic-angular';
import { Geolocation } from '@ionic-native/geolocation';

declare var google;

@Component({
  selector: 'home-page',
  templateUrl: 'home.html'
})
export class HomePage {

  @ViewChild('map') mapElement: ElementRef;
  map: any;

  constructor(public navCtrl: NavController, public geolocation: Geolocation) {

  }

  ionViewDidLoad(){
    this.loadMap();
  }

  loadMap(){

    this.geolocation.getCurrentPosition().then((position) => {

      let latLng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);

      let mapOptions = {
        center: latLng,
        zoom: 15,
        mapTypeId: google.maps.MapTypeId.ROADMAP
      }

      this.map = new google.maps.Map(this.mapElement.nativeElement, mapOptions);

    }, (err) => {
      console.log(err);
    });

  }

}

NOTE: Make sure your browser does not block the request for getting the users position, otherwise this function will not run and your map will not load.

The Geolocation API is asynchronous (meaning the code will not wait for the result before continuing), and the code inside of the fat arrow function (=>) will run when the position has been successfully retrieved.

The “fat arrow” functions may look a little bit confusing at first, but they are essentially just replacing the callback functions. So that this:

function(success){
    console.log(success);
}

becomes this:

(success) => {
    console.log(success);
}

so just drop the “function” and add an arrow “=>” – easy! One of the main benefits of doing this is that code executed within the fat arrow function will have the same scope as its parent (meaning you don’t need to do things like var me = this or var that = this).

The position object that is returned will contain the current latitude and longitude of the user, which we use to create our LatLng object instead of the hard coded values we were using before.

3. Adding Markers and Info Windows to the Map

Markers are a very commonly used feature in map applications, so we definitely want to take a look at how to add those. We’ve already got a button that calls an addMarker function, now we just need to create that in home.ts.

Add the following function to src/pages/home/home.ts

addMarker(){

  let marker = new google.maps.Marker({
    map: this.map,
    animation: google.maps.Animation.DROP,
    position: this.map.getCenter()
  });

  let content = "<h4>Information!</h4>";          

  this.addInfoWindow(marker, content);

}

This is a pretty simple function, we’re just using the Marker function provided by the Google Maps API. Simply by creating the marker variable with this function, the marker will automatically be added to the map we specify.

After that, we’re also creating some content and adding an info window that will be shown when the user taps on the marker. If you don’t want info windows, you can just remove those last two lines, but if you do want them, make sure to add the following function as well.

Add the following function to src/pages/home/home.ts

  addInfoWindow(marker, content){

    let infoWindow = new google.maps.InfoWindow({
      content: content
    });

    google.maps.event.addListener(marker, 'click', () => {
      infoWindow.open(this.map, marker);
    });

  }

This just creates a new info window by using another function provided by the Google Maps API, and then we set up a click listener on the marker that the info window is for.

If you run your application now you should see the map centered on your current location, and you should be able to add markers to the center of the map by clicking the + Add Marker button.

Summary

This is a very basic implementation of Google Maps in an Ionic 2 application, but it covers most of the core concepts you will need to know (initiating the map, adding markers and adding info windows). As I mentioned before, if you are creating an application with a lot of markers then you should take some steps to optimise how those markers are rendered. I will create a tutorial for doing that in Ionic 2 at some point, but for now you can take a look at how I did that with Ionic 1.

What to watch next...