0% found this document useful (0 votes)
15 views

@ionic Native - Google Maps

Uploaded by

Lewis Zap
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views

@ionic Native - Google Maps

Uploaded by

Lewis Zap
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 110

@ionic-native / google-maps

Cordova GoogleMaps plugin project

Masashi Katsumata
Ionic framework
@ionic-native/google-maps
● Embed native Google Maps view in your app

● One code for both Android, iOS and Browser (from v4.12.0)

● Easy to use

● Faster than Google Maps Javascript API v3

● Free to use. Apache License v2


・UI components
Yo ・View management
u ・TypeScript -> JS
this r cod
bro e ru ...etc
ws no
er
vie n
w

b e t ween
e
Bridg system
e
nativ ur code!
o
and y
@ionic-native/google-maps

Let’s see the


demo!
<b
utto
n io
n-b
utt
o
(HT n>
ML
) a p!
e M w)
l e
o og e vi
G ativ
(n
ap
The M
is
able
touch
The M
ap
is not
s i d e menu toucha
ble!
The
is
u c h able!!
to
Google Map View is under the browser!!
(and this is not a HTML element)

This is native
Google Maps
view, which is not
a HTML element.
u c h layer
to
e)
(nativ

Is this on map
or browser?

Pass
the touch event to
the map or browser
Hello world
API key

Create a project https://cloud.google.com/maps-platform/#get-started


API key

Create a project
https://cloud.google.com/maps-platform/#get-started
API key

Enable billing
You need to register your
payment way.

But don’t worry, you probably


won’t charge.
Because Google Maps Android
API and Google Maps SDK for
iOS are free.
(Except geocoding, StreetView)
Are Google Maps APIs free to use?
● Yes!!
"Google Maps Android API v2" and "Google Maps SDK for iOS" are free, and
unlimited usage (at this time)! Thus, this plugin is also free!

● But no!!
If you run your app on the browser platform, this plugin uses Google Maps
JavaScript API v3.

● Bonus: you can get $200 credit / month for other Maps APIs
(Google Directions API, Google Maps JavaScript API v3, and so on)
API key

Enable Google Maps APIs


API key

Enable Google Maps APIs

This
i
API s your
key

Restrict your key when


you release your app
API key Create project

Create a project
$> ionic start myApp sidemenu --type=angular
? Integrate your new app with Cordova to target native iOS and Android? YES

$> npm install @ionic-native/core

$> npm install @ionic-native/google-maps


API key Create project

Install cordova-plugin-googlemaps

$> ionic cordova plugin add cordova-plugin-googlemaps


API key Create project

Edit `config.xml`

<?xml version='1.0' encoding='utf-8'?>


<widget ...>

<preference
name="GOOGLE_MAPS_ANDROID_API_KEY" value="(api key)" />
<preference
name="GOOGLE_MAPS_IOS_API_KEY" value="(api key)" />

</widget>
API key Create project HTML & CSS

src/app/home/home.page.html

<ion-content padding>
<h3>Ionic GoogleMaps Starter</h3>

<div id="map_canvas">
<button ion-button (click)="onButtonClick($event)">Start demo</button>
</div>

</ion-content> Ad
da
div
(m
ap
div
)
API key Create project HTML & CSS

src/pages/home/home.scss
Background styles become be transparent
#map_canvas { by the maps plugin mandatory!
height: 90%;
} You can set the background color through
Environment.setBackgroundColor()

100 x 100 pixels are minimum requirement


dimension.
API key Create project HTML & CSS Coding

src/app/home/home.page.ts
import { Component, OnInit } from '@angular/core';
import { Platform } from '@ionic/angular';
import { GoogleMaps, GoogleMap } from '@ionic-native/google-maps/ngx';

export class HomePage implements OnInit {

map: GoogleMap;

constructor(private platform:Platform) {}

async ngOnInit() {
// you need to wait `platform.ready()`
await this.platform.ready(); Important!!!

await this.loadMap();
}
If you forget that …

ionViewDidLoad() is executed
(DOM elements are ready)

Then you get this error message

platform.ready() is executed later


(the native plugins are ready to use)
API key Create project HTML & CSS Coding

src/app/home/home.page.ts
loadMap() {
// If you want to run your app
// on browser, insert this line.
Environment.setEnv({
'API_KEY_FOR_BROWSER_RELEASE': '',
'API_KEY_FOR_BROWSER_DEBUG':''
});

// Create a map
// after the view is ready
// and the native platform is ready.
this.map = GoogleMaps.create('map_canvas');

}
API key Create project HTML & CSS Coding Run it!

Run it!!
$> ionic cordova run android $> ionic cordova run browser -l
Marker

@ionic-native/google-maps
Add a marker
this.map.addMarker({
title: '@ionic-native/google-maps',
icon: 'blue',
animation: 'DROP',
position: {
lat: 43.0741904,
lng: -89.3809802
}
}).then((marker: Marker) => {

marker.showInfoWindow();

});
Add a marker from v4.8.2 -

let marker: Marker = this.map.addMarkerSync({


title: '@ionic-native/google-maps',
icon: 'blue',
animation: 'DROP',
position: {
lat: 43.0741904,
lng: -89.3809802
}
});

marker.showInfoWindow();
icon property
this.map.addMarkerSync({ color name : blue, red, green, yellow ....
title: '@ionic-native/google-maps', (157 color names are defined in this plugin)
icon: 'blue',
animation: 'DROP', rgb(), rgba() , hsl(), hsla(), #RGB, #RGBA
position: { :
./assets/icon.png (jpg, gif, and png) :
lat: 43.0741904,
lng: -89.3809802 http(s)://yourserver/icon.png :
}
}); cdvfile:// …. /icon.png :

data:image/png;base64,iVBORw0KGgo...CC :
:
icon property
let POINTS: BaseArrayClass<any> = new BaseArrayClass<any>([
{
position: {lat:41.79883, lng:140.75675},
iconData: "./assets/imgs/Number-1-icon.png"
},
{
position: {lat:41.799240000000005, lng:140.75875000000002},
iconData: "http://icons.iconarchive.com/.../24/Number-2-icon.png"
},
{
position: {lat:41.797650000000004, lng:140.75905},
iconData: {
url: "http://icons.iconarchive.com/.../48/Number-3-icon.png",
size: { width: 24, height: 24}
}
},
{
position: {lat:41.79637, lng:140.76018000000002},
title: "4",
iconData: "blue"
},
{
position: {lat:41.79567, lng:140.75845},
title: "5",
iconData: "data:image/png;base64,iVBORw...CC"
}
]);
Marker events
● MARKER_CLICK

● MARKER_DRAG_START
● MARKER_DRAG
● MARKER_DRAG_END

● INFO_CLICK
● INFO_LONG_CLICK
● INFO_OPEN
● INFO_CLOSE
Add event listener
Listen the event only one time
marker.addEventListenerOnce(GoogleMapsEvent.MARKER_CLICK).then();

// Alias method
marker.one(GoogleMapsEvent.MARKER_CLICK).then();

Listen the event multiple times


marker.addEventListener(GoogleMapsEvent.MARKER_CLICK).subscribe();

// Alias method
marker.on(GoogleMapsEvent.MARKER_CLICK).subscribe();
Remove event listener
Listen the event only one time
// Remove particular event listener
marker.off(GoogleMapsEvent.MARKER_CLICK, this.onMarkerClick);

// Remove all event listeners for the MARKER_CLICK event


marker.off(GoogleMapsEvent.MARKER_CLICK);

// Remove all event listeners of all events


marker.off();
Example
this.map.addMarker({
position: {
lat: 43.0741804,
lng: -89.381
},
title: "A",
disableAutoPan: true
}).then(this.onMarkerAdded);

this.map.addMarker({
position: {
lat: 43.0741804,
lng: -89.382
},
title: "B",
disableAutoPan: true
}).then(this.onMarkerAdded);

onMarkerAdded(marker: Marker) {
marker.one(GoogleMapsEvent.MARKER_CLICK).then(() => {
alert("Marker" + marker.getTitle() + " is clicked");
});
}
Polyline

@ionic-native/google-maps
Polyline
let AIR_PORTS = [
HND_AIR_PORT, HNL_AIR_PORT, SFO_AIR_PORT
];

this.map.addPolyline({
points: AIR_PORTS, Click e
ve
color: '#AA00FF', (Becaus nt with LatL
e this ng
width: 10, plugin
calcula
geodesic: true, tes own
way)
clickable: true // clickable = false in default
}).then((polyline: Polyline) => {
polyline.on(GoogleMapsEvent.POLYLINE_CLICK).subscribe((params: any) => {
let position: LatLng = <LatLng>params[0];
this.map.addMarker({
position: position,
title: position.toUrlValue(),
disableAutoPan: true
}).then((marker: Marker) => {
marker.showInfoWindow();
});
});
});
Polyline from v4.8.2 -
let AIR_PORTS = [
HND_AIR_PORT, HNL_AIR_PORT, SFO_AIR_PORT
];

let polyline: Polyline = this.map.addPolylineSync({


points: AIR_PORTS,
color: '#AA00FF',
width: 10,
geodesic: true,
clickable: true // clickable = false in default
})

polyline.on(GoogleMapsEvent.POLYLINE_CLICK).subscribe((params: any) => {


let position: LatLng = <LatLng>params[0];
let marker: Marker = this.map.addMarkerSync({
position: position,
title: position.toUrlValue(),
disableAutoPan: true
});
marker.showInfoWindow();
});
Polygon

@ionic-native/google-maps
Polygon
let GORYOKAKU_POINTS: ILatLng[] = [
{lat: 41.79883, lng: 140.75675},
{lat: 41.799240000000005, lng: 140.75875000000002},
{lat: 41.797650000000004, lng: 140.75905},

{lat: 41.79909000000001, lng: 140.75465}
]; ng[]
s I LatL
pas
this.map.addPolygon({ Just
'points':GORYOKAKU_POINTS,
'strokeColor' : '#AA00FF',
'fillColor' : '#00FFAA',
'strokeWidth': 10
}.then((polygon: Polygon) => {

...

});
Polygon from v4.8.2 -

let GORYOKAKU_POINTS: ILatLng[] = [


{lat: 41.79883, lng: 140.75675},
{lat: 41.799240000000005, lng: 140.75875000000002},
{lat: 41.797650000000004, lng: 140.75905},

{lat: 41.79909000000001, lng: 140.75465}
];

let polygon: Polygon = this.map.addPolygonSync({


'points':GORYOKAKU_POINTS,
'strokeColor' : '#AA00FF',
'fillColor' : '#00FFAA',
'strokeWidth': 10
});
Circle

@ionic-native/google-maps
Circle
let center: ILatLng = {"lat": 32, "lng": -97};
let radius = 300; // radius (meter)

this.map.addCircle({
'center': center,
'radius': radius,
'strokeColor' : '#AA00FF',
'strokeWidth': 5,
'fillColor' : '#00880055'
}).then((circle: Circle) => {

marker.on('position_changed').subscribe((params: any) => {


let newValue: ILatLng = <ILatLng>params[1];

let newRadius: number = Spherical.computeDistanceBetween(


center, newValue);

circle.setRadius(newRadius);
});
});
Circle from v4.8.2 -

let center: ILatLng = {"lat": 32, "lng": -97};


let radius = 300; // radius (meter)

let circle: Circle = this.map.addCircleSync({


'center': center,
'radius': radius,
'strokeColor' : '#AA00FF',
'strokeWidth': 5,
'fillColor' : '#00880055'
});

marker.on('position_changed').subscribe((params: any) => {


let newValue: ILatLng = <ILatLng>params[1];

let newRadius: number = Spherical.computeDistanceBetween(


center, newValue);

circle.setRadius(newRadius);
});
GroundOverlay

@ionic-native/google-maps
GroundOverlay
this.map.one(GoogleMapsEvent.MAP_READY).then(() => {
return this.map.addGroundOverlay({
'url': 'assets/imgs/newark_nj_1922.jpg',
'bounds': bounds,
'opacity': 0.5,
'clickable': true // default = false
});
}).then((groundOverlay: GroundOverlay) => {

// Catch the GROUND_OVERLAY_CLICK event


groundOverlay.on(GoogleMapsEvent.GROUND_OVERLAY_CLICK).subscribe(() => {
groundOverlay.setImage('assets/imgs/newark_nj_1922_2.jpg');
});

});
GroundOverlay from v4.8.2 -

let groundOverlay: GroundOverlay = this.map.addGroundOverlaySync({


'url': 'assets/imgs/newark_nj_1922.jpg',
'bounds': bounds,
'opacity': 0.5,
'clickable': true // default = false
});
});

// Catch the GROUND_OVERLAY_CLICK event


groundOverlay.on(GoogleMapsEvent.GROUND_OVERLAY_CLICK).subscribe(() => {
groundOverlay.setImage('assets/imgs/newark_nj_1922_2.jpg');
});
TileOverlay

@ionic-native/google-maps
TileOverlay
You can
generat
e vario
us URL
this.map.addTileOverlay({
getTile: (x: number, y: number, zoom: number) => {
return "http://tile.stamen.com/watercolor/" +
zoom + "/" + x + "/" + y + ".jpg";
},

// draw the debug information on tiles


debug: false,

opacity: 1.0
});
TileOverlay from v4.8.2 -

let tileOverlay: TileOverlay = this.map.addTileOverlaySync({


getTile: (x: number, y: number, zoom: number) => {
return "http://tile.stamen.com/watercolor/" +
zoom + "/" + x + "/" + y + ".jpg";
},

// draw the debug information on tiles


debug: false,

opacity: 1.0
});
HtmlInfoWindow

@ionic-native/google-maps
HtmlInfoWindow(1)
let htmlInfoWindow = new HtmlInfoWindow();
let frame: HTMLElement = document.createElement('div');
frame.innerHTML = [
'<h3>Hearst Castle</h3>',
'<img src="assets/imgs/hearst_castle.jpg">'
].join("");
frame.getElementsByTagName("img")[0].addEventListener("click", () => {
htmlInfoWindow.setBackgroundColor('red');
});
htmlInfoWindow.setContent(frame, {width: "280px", height: "330px"});

this.map.addMarker({
position: {lat: 35.685208, lng: -121.168225},
draggable: true,
disableAutoPan: true
}).then((marker: Marker) => {
marker.on(GoogleMapsEvent.MARKER_CLICK).subscribe(() => {
htmlInfoWindow.open(marker);
});
});
HtmlInfoWindow(2) Full source code

onMarkerClick(params: any[]) {
// Get a marker instance from the passed parameters
let marker: Marker = params.pop();

// Create a component
const compFactory = this.resolver.resolveComponentFactory(CustomTag);
let compRef: ComponentRef<CustomTag> =
compFactory.create(this.injector);
compRef.instance.myTitle = marker.get('myTitle');
this.appRef.attachView(compRef.hostView);

let div = document.createElement('div');


div.appendChild(compRef.location.nativeElement);

// Dynamic rendering
this._ngZone.run(() => {
this.htmInfoWindow.setContent(div);
this.htmInfoWindow.open(marker);
});
}
Marker cluster

@ionic-native/google-maps
MarkerCluster
this.map.addMarkerCluster({
markers: data,
icons: [
{
min: 3, max: 9,
url: "./assets/markercluster/small.png",
label: { color: "white" }
},
{
min: 10,
url: "./assets/markercluster/large.png",
label: { color: "white" }
}
]
}).then((markerCluster: MarkerCluster) => {

markerCluster.on(GoogleMapsEvent.MARKER_CLICK).subscribe((params) => {
let marker: Marker = params[1];
marker.setTitle(marker.get("name"));
marker.setSnippet(marker.get("address"));
marker.showInfoWindow();
});

});
MarkerCluster from v4.8.2 -

let markerCluster: MarkerCluster = this.map.addMarkerClusterSync({


markers: data,
icons: [
{
min: 3, max: 9,
url: "./assets/markercluster/small.png",
label: { color: "white" }
},
{
min: 10,
url: "./assets/markercluster/large.png",
label: { color: "white" }
}
]
});

markerCluster.on(GoogleMapsEvent.MARKER_CLICK).subscribe((params) => {

let marker: Marker = params[1];


marker.setTitle(marker.get("name"));
marker.setSnippet(marker.get("address"));
marker.showInfoWindow();

});
Geocoding

@ionic-native/google-maps
Geocoding
ess
// Address -> latitude,longitude addr
one
g for
Geocoder.geocode({ odin
Geoc
"address": this.search_address
})
.then((results: GeocoderResult[]) => {
console.log(results);

return this.map1.addMarker({
'position': results[0].position,
'title': JSON.stringify(results[0].position)
})
})
.then(...)
Batch geocoding rray
n s as a
Geocoder.geocode({ tio
loca
Pass
// US Capital cities
"address": [
"Montgomery, AL, USA", "Juneau, AK, USA", ...
"Madison, WI, USA", "Cheyenne, Wyoming, USA"
]
})
.then((mvcArray: BaseArrayClass<GeocoderResult[]>) => {
Get
}); a
then mvc ar
r
noti `finish ay firs
fied ` ev t
. ent ,
is

Just
1.9 s
ec!
BaseClass

@ionic-native/google-maps
All classes extend Base class

GroundOverlay TileOverlay MarkerCluster

Circle Polyline Polygon

BaseArrayClass Map Marker

BaseClass
BaseClass
● set()

● get()

● bindTo()

● trigger()

● on() / addEventListener()

● one() / addEventListenerOnce()

● off()

● empty()

● destroy()
set() and get() obj.set(key, value, noNotify?)
obj.get(key)

let myObj: BaseClass = new BaseClass();

myObj.set("hello", "world");
"Hel
lo_c
console.log(myObj.get("hello")); hang
ed"
even
t oc
curs
(key)_changed event
let myObj: BaseClass = new BaseClass();

myObj.on("hello_changed").subscribe((params) =>an{ged
h
console.log(params); o_c
hell
});

myObj.set("hello", "world");
myObj.set("hello", "world2"); hello_c
hange
d
Status change event anged
_ch
ition
pos

marker.setPosition(...);

title_changed

marker.setTitle("....");
Own property
this.map.addMarker({
position: { lat: 43.0741704, lng: -89.3809802},
count: 0
})
.then((marker: Marker) => {
marker.on(GoogleMapsEvent.MARKER_CLICK).subscribe(() => {
marker.set("count", marker.get("count") + 1);
});

marker.on("count_changed").subscribe((params: []) => {


let oldValue = params[0];
let newValue = params[1];
let key = params[2];
marker.setTitle("'" + key + "' is changed from '" +
oldValue + "' to '" + newValue + "'");
});

});
Own property from v4.8.2 -

let marker: Marker = this.map.addMarkerSync({


position: { lat: 43.0741704, lng: -89.3809802},
count: 0
});
marker.on(GoogleMapsEvent.MARKER_CLICK).subscribe(() => {
marker.set("count", marker.get("count") + 1);
});

marker.on("count_changed").subscribe((params: []) => {


let oldValue = params[0];
let newValue = params[1];
let key = params[2];
marker.setTitle("'" + key + "' is changed from '" +
oldValue + "' to '" + newValue + "'");
});
noNotify option
let myObj: BaseClass = new BaseClass();

myObj.on("hello_changed").subscribe((params) => { DO N
OT
console.log(params); OCC
UR
}); hello_changed

myObj.set("hello", "world", true);


bindTo() sourceObj.bindTo(targetKey, dest, destKey?, noNotify?)

let objA: BaseClass = new BaseClass();


let objB: BaseClass = new BaseClass();

objA.bindTo("hello", objB, "world");

objA.set("hello", "こんにちは");
objB.get("world");

objA objB

hello world

"こんにちは" "こんにちは"
bindTo()
this.map.addMarker({
position: {lat: 43.0741704, lng: -89.3809802},
draggable: true
})
.then((marker: Marker) => {
this.map.addCircle({
center: marker.getPosition(),
radius: 10,
fillColor: "rgba(0, 0, 255, 0.5)",
strokeColor: "rgba(0, 0, 255, 0.75)",
strokeWidth: 1
}).then((circle: Circle) => {
marker.bindTo("position", circle, "center");
});
});
bindTo() from v4.8.2 -

let marker: Marker = this.map.addMarkerSync({


position: {lat: 43.0741704, lng: -89.3809802},
draggable: true
});
let circle: Circle = this.map.addCircleSync({
center: marker.getPosition(),
radius: 10,
fillColor: "rgba(0, 0, 255, 0.5)",
strokeColor: "rgba(0, 0, 255, 0.75)",
strokeWidth: 1
});

marker.bindTo("position", circle, "center");


trigger() obj.trigger(eventName, args?...)

createMarkers() {
let bounds = this.map.getVisibleRegion();
let sw = bounds.southwest, ne = bounds.northeast;
let diffY = (ne.lat - sw.lat), diffX = (ne.lng - sw.lng);
for (let i = 0; i < 10; i++) {
this.map.addMarker({
'position': {
'lat': sw.lat + diffY * Math.random(),
'lng': sw.lng + diffX * Math.random()
}
}).then((marker:Marker) => {
this.map.on('animate').subscribe((params: []) => {
let animation: string = params[0];
marker.setAnimation(animation);
});
});
}
}
onButtonClick() {
let btnTxt: string = event.srcElement.innerText;
this.map.trigger("animate", btnTxt);
}
Deep understanding
Internal command queue
Cordova executes all methods in asynchronously!
this.map.addMarker({ .then((marker:Marker) =>
… {
})
});

exec("Map", "loadPlugin",
"Marker");

map.addMarker()
(native code)
What would be occurred like this code?
this.map.clear();

for (let i = 0; i < positions.length; i++) {

this.map.addMarker({
position: positions[i]
}).then((marker: Marker) => {

this.markers.push(marker);

});

}
map.clear() is slow...
Correct way:
this.map.clear();
this.map.clear().then(() => {
for (let i = 0; i < positions.length; i++) { ….
});
this.map.addMarker({
position: positions[i]
}).then((marker: Marker) => {

this.markers.push(marker);

});

}
Don’t worry, this plugin handles correctly!
this.map.clear();

for (let i = 0; i < positions.length; i++) {

this.map.addMarker({
position: positions[i]
}).then((marker: Marker) => {

this.markers.push(marker);

});

}
Because this plugin has own command queue!
Execute method in synchronous
map.clear()
(Stop all other methods)

addMarker() addMarker() addMarker() addMarker() addMarker()

addMarker() addMarker() addMarker() addMarker() addMarker()

addMarker() addMarker() addMarker() addMarker() addMarker()

addMarker() addMarker() addMarker() addMarker() addMarker()

Execute 10 methods in parallel at a once


Limit 10 is problem sometimes...

Sorry, there is no solution currently.


synchronous methods
● googleMaps.create() ● map.animateCamera()
● map.setCameraZoom() ● map.moveCamera()
● map.panBy() ● map.setMyLocationEnabled()
● map.clear() ● map.getMyLocation()
● map.setCameraTilt() ● map.remove()
● map.setCameraBearing() ● map.setDiv()
● map.moveCameraZoomIn()
● map.moveCameraZoomOut()
● map.animateCameraZoomIn()
● map.animateCameraZoomOut()
@ionic-native/google-maps
version 4.8.2

Breaking changes are introduced


You
Add new methods: Used be ... ca
this n still
synt u
ax c se
this.map.addMarker({ ode
position: {lat: …, lng: …},
● map.addMarkerSync() title: "Hello world"
}).then((marker:Marker) => {
● map.addCircleSync() marker.showInfoWindow();
● map.addPolylineSync() });
● map.addPolygonSync()
● map.addTileOverlaySync() from v4.8.2 -
● map.addGroundOverlaySync() let marker:Marker = this.map.addMarkerSync({
● map.addMarkerClusterSync() position: {lat: …, lng: …},
title: "Hello world"
});

marker.showInfoWindow();
MAP_READY event
Used be ...

this.map = GoogleMaps.create('map_canvas');
this.map.one(GoogleMapsEvent.MAP_READY).then(() => {
this.map.addMarker({
position: {lat: …, lng: …},
title: "Hello world"
});
});
from v4.8.2 -

this.map = GoogleMaps.create('map_canvas');

let marker:Marker = this.map.addMarkerSync({


position: {lat: …, lng: …},
title: "Hello world"
});
However, if you use map.getVisibleRegion()...
this.map = GoogleMaps.create('map_canvas');

let visibleRegion: VisibleRegion = this.map.getVisibleRegion();

console.log(visibleRegion); // == null

You still have to need to wait


MAP_READY event for this case!
StreetView panorama
class StreetViewPage {
let panorama: StreetViewPanorama;

ionViewDidLoad() {
this.loadPanorama();
}

loadPanorama() {

// Create a map after the view is loaded.


// (platform is already ready in app.component.ts)
this.panorama = GoogleMaps.createPanorama('pano_canvas', {
camera: {
target: {lat: 42.345573, lng: -71.098326}
}
});

}
}
BaseArrayClass

@ionic-native/google-maps
BaseArrayClass
● map() ● indexOf() ● insertAt()

● mapAsync() ● empty() ● getArray()

● forEach() ● push() ● getAt()

● forEachAsync() ● pop() ● setAt()

● filter() ● removeAt()

● filterAsync() ● getLength()

● reverse()

● sort()
forEach() baseArray.forEach(fn)

0 1 2 3 4
forEach() baseArray.forEach(fn)

let baseArray: BaseArrayClass<ILatLng> = new BaseArrayClass(positions);

baseArray.forEach((position: ILatLng, idx: number) => {

this.map.addMarker({
position: position
}).then((marker: Marker) => {
this.markers.push(marker);
});

});
forEachAsync() baseArray.forEachAsync(fn).then()

Async task
(i.e. setTimeout())
0 1 2 3 4
forEachAsync() baseArray.forEachAsync(fn).then()

let baseArray: BaseArrayClass<ILatLng> = new BaseArrayClass(positions);

baseArray.forEachAsync((position: ILatLng, next:() => void) => {

this.map.addMarker({
position: position
}).then((marker: Marker) => {
this.markers.push(marker);
next();
});

}.then(() => {
console.log('finish!');
});
map() baseArray.map(fn)

0 1 2 3 4

a b c d e

a b c d e
map() baseArray.map(fn)

let baseArray: BaseArrayClass<Marker> = new BaseArrayClass(this.markers);

let titles: [] = baseArray.map((marker: Marker, idx: number) => {

return marker.getTitle();

});
mapAsync() baseArray.mapAsync(fn).then()

0 1 2 3 4 Async task
(i.e. setTimeout())

a b c d e

a b c d e
mapAsync() baseArray.mapAsync(fn).then()

let baseArray: BaseArrayClass<ILatLng> = new BaseArrayClass(positions);

baseArray.mapAsync((position: ILatLng, next: (result: any) => void) => {

this.map.addMarker({
position: position
}).then(next);

}).then(markers: Marker[]) => {


console.log('finish!');
});
filter() baseArray.filter(fn)

0 1 2 3 4

true false true false true

a c e
filter() baseArray.filter(fn)

let baseArray: BaseArrayClass<Marker> = new BaseArrayClass(this.markers);

let matchedMarkers: [] = baseArray.filter((marker: Marker, idx: number) => {

return marker.get('category') === 'restaurant';

});
filterAsync() baseArray.filterAsync(fn).then()

0 1 2 3 4 Async task
(i.e. setTimeout())

true false true false true

a c e
filterAsync() baseArray.filterAsync(fn).then()

let baseArray: BaseArrayClass<Marker> = new BaseArrayClass(this.markers);

baseArray.filter((marker: Marker, next: (result: boolean) => void) => {

// i.e. Get data from remote database


http_request
.get('https://yourserver/getData/', {id: marker.get('dbId')})
.then((locationData: object) => {

// detect later Asynchronous


process
next(location.category === 'restaurant');
});

}).then(matchedMarkers: Marker[]) => {


console.log('finish');
});
push(), pop()
let baseArray: BaseArrayClass = new BaseArrayClass();

at event
insert_
baseArray.push('a');

baseArray.push('b');

baseArray.push('c');
remove_at event
baseArray.pop();

baseArray.pop();

baseArray.pop();
BaseArrayClass example
let points: ILatLng[] = [
{lat: 33.91636924837674, lng: -118.39605331420898},
{lat: 33.90205144970967, lng: -118.39639663696288},
{lat: 33.90190897196702, lng: -118.37905883789062},
{lat: 33.89471353635718, lng: -118.3787155151367}
];

this.map = this.googleMaps.create('map_canvas', {
camera: {
target: points
}
});

this.map.one(GoogleMapsEvent.MAP_READY).then(() => {
return this.map.addPolyline({
points: points
});
})

//continue to next page...


BaseArrayClass example
.then((polyline: Polyline) => {
let baseArray: BaseArrayClass<ILatLng> = polyline.getPoints(); polyline.getPoints() returns
BaseArrayClass
baseArray.mapAsync((point: ILatLng, next: Function) => {
this.map.addMarker({
position: point,
draggable: true
}).then(next);
}, (markers: Marker[]) => {
markers.forEach((marker: Marker, idx: number) => {
marker.on('position_changed').subscribe((params: []) => {
baseArray.setAt(idx, params[1]);
});
});

// trigger the position_changed event for the first calculation. nce


e d ista dragged
e th rs are
markers[0].trigger('position_changed', null, markers[0].getPosition());
ulat e
});
Calc ny mark
baseArray.on('set_at', () => { e n a
wh
this._ngZone.run(() => {
let distanceMeter: number = Spherical.computeLength(baseArray);
this.distance = (distanceMeter * 0.000621371192).toFixed(2) + " miles";
});
});
});
BaseArrayClass example
KML Overlay

@ionic-native/google-maps
KML overlay
this.loading = this.loadingCtrl.create({
content: 'Please wait...'
});
this.loading.present();

this.map.addKmlOverlay({
url: "assets/kmloverlay/polygon.kml"
}).then((kmlOverlay: KmlOverlay) => { Fits cam
era
this.loading.dismiss(); to view
kml
overall
console.log(kmlOverlay);

this.map.moveCamera(kmlOverlay.getDefaultViewport());

// You can get additional information


kmlOverlay.on(GoogleMapsEvent.KML_CLICK).subscribe((params: any) => {
let overlay: Polygon = params[0]; // depends on overlay
let latLng: ILatLng = params[1];
console.log(overlay, latLng);
});

});
LocationService

@ionic-native/google-maps
LocationService
let option: MyLocationOptions = {
// true: use GPS as much as possible (use battery usage alot)
//
// false: use network location or lastKnownLocation
// (save battery usage)
enableHighAccuracy: true
};

LocationService.getMyLocation(option).then((location: MyLocation) => {


this.map = GoogleMaps.create({
'camera': location.latLng,
'zoom': 16
});

...
}).catch((error: any) => {
// Can not get location, permission refused, and so on...
console.log(error);
});
Good example projects

How to use this plugin in real project


Main page + detail page

Special thanks for battika


Use two maps in two pages
https://github.com/battika/ionic-gmaps-test

There is a map and “Open Second Page” button in home.html.


If you tap on the button, open a detail page using
this.navCtrl.push(SecondPage,{},{animate:false});

In this case, ionic keeps the first page but css visibility = hidden.
The maps plugin can detect this particular case, and detach the main
page map automatically.
Then create another map for detail page.

After closing the second page, there is no more div element for the
second map. So the maps plugin destroys the second map automatically.

Then the maps plugin attaches the map view to browser automatically,
when the main page becomes visibility = visible.
Plugin repository
https://github.com/mapsplugin/
cordova-plugin-googlemaps
Cordova GoogleMaps plugin
author Official documents
https://github.com/ionic-team/ionic-n
& ative-google-maps/blob/master/docu
ments/README.md
Google Developers Expert of
Google Maps API Code repository
https://github.com/mapsplugin/ionic-
Masashi Katsumata googlemaps-quickdemo

You might also like