SlideShare a Scribd company logo
1 of 85
Download to read offline
@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 and iOS
● Easy to use
● Faster than Google Maps Javascript API v3
● Free to use. Apache License v2
・UI components
・View management
・TypeScript -> JS
...etc
Your code run on
this browser view
Bridge between
native system
and your code!
@ionic-native/google-maps
Let’s see the
demo!
<button ion-button>(HTML)
Google Map!
(native view)
The Map
is
touchable
The side menu
is
touchable!!
The Map
is not
touchable!
Google Map is under the browser!!
touch layer
(native)
Is this on map
or browser?
Pass
the touch event to
the map or browser
Hello world
Google Maps API key
https://console.developers.google.com/projectselector/apis/library
API key
Enable Google Maps APIs
Enable Both APIs
API key
Create credential
Start from here!
API key
Generate an API key
This is the API key
Restrict your key
when you
release your app
API key
Create a project & install plugins
$> ionic start myApp sidemenu
$> npm install @ionic-native/google-maps @ionic-native/core
$> ionic cordova plugin add cordova-plugin-googlemaps
--variable API_KEY_FOR_ANDROID=”.....”
--variable API_KEY_FOR_IOS=”.....”
Please use the
latest version
anytime!
API key Create project
app/src/app.module.ts
Add this line
Add this line
API key Create project
import { BrowserModule } from '@angular/platform-browser';
...
import { GoogleMaps } from "@ionic-native/google-maps";
@NgModule({
....
providers: [
StatusBar,
SplashScreen,
GoogleMaps,
{provide: ErrorHandler, useClass: IonicErrorHandler}
]
})
export class AppModule {}
src/pages/home/home.html
Add a div (map div)
API key Create project HTML & CSS
<ion-content padding>
<h3>Ionic GoogleMaps Starter</h3>
<div id="map_canvas">
<button ion-button (click)="onButtonClick($event)">Start demo</button>
</div>
</ion-content>
src/pages/home/home.scss
page-home {
#map_canvas {
height: 90%;
}
}
Background styles become be transparent
by the maps plugin mandatory!
You can set the background color through
Environment.setBackgroundColor()
API key Create project HTML & CSS
src/app/app.components.ts
API key Create project HTML & CSS Coding
export class MyApp {
@ViewChild(Nav) nav: Nav;
rootPage: any;
constructor(public platform: Platform, public statusBar: StatusBar, public splashScreen: SplashScreen) {
this.initializeApp();
}
initializeApp() {
this.platform.ready().then(() => {
this.rootPage = HomePage;
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
this.statusBar.styleDefault();
this.splashScreen.hide();
});
}
Set the first page
after the platform.read() is called
If you forget that …
ionViewDidLoad() is executed
(DOM elements are ready)
platform.ready() is executed later
(the native plugins are ready to use)
Then you get this error message
src/pages/home/home.ts
API key Create project HTML & CSS Coding
import { GoogleMaps, GoogleMap, GoogleMapsEvent } from '@ionic-native/google-maps';
export class HomePage {
map: GoogleMap;
constructor( public navCtrl: NavController, private googleMaps: GoogleMaps ) { }
ionViewDidLoad() {
this.loadMap();
}
src/pages/home/home.ts
loadMap() {
// Create a map after the view is ready and the native platform is ready.
this.map = this.googleMaps.create('map_canvas');
// Wait the maps plugin is ready until the MAP_READY event
this.map.one(GoogleMapsEvent.MAP_READY).then(() => {
console.log('map is ready to use.');
});
}
API key Create project HTML & CSS Coding
Run it!!
$> ionic cordova run android
API key Create project HTML & CSS Coding Run it!
Marker
@ionic-native/google-maps
Add a marker
this.map.addMarker({
title: 'Ionic',
icon: 'blue',
animation: 'DROP',
position: {
lat: 43.0741904,
lng: -89.3809802
}
}).then((marker: Marker) => {
marker.showInfoWindow();
});
icon property
this.map.addMarker({
title: 'Ionic',
icon: 'blue',
animation: 'DROP',
position: {
lat: 43.0741904,
lng: -89.3809802
}
}).then((marker: Marker) => {
marker.showInfoWindow();
});
color name : blue, red, green, yellow ....
(157 color names are defined in this plugin)
rgb(), rgba() , hsl(), hsla(), #RGB, #RGBA
:
./assets/icon.png (jpg, gif, and png) :
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
Listen the event multiple times
marker.addEventListenerOnce(GoogleMapsEvent.MARKER_CLICK).then();
// Alias method
marker.one(GoogleMapsEvent.MARKER_CLICK).then();
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,
color: '#AA00FF',
width: 10,
geodesic: true,
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();
});
});
});
Click event with LatLng
(Because this plugin calculates own way)
Polygon
@ionic-native/google-maps
Polygon
Just pass ILatLng[]
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}
];
this.map.addPolygon({
'points':GORYOKAKU_POINTS,
'strokeColor' : '#AA00FF',
'fillColor' : '#00FFAA',
'strokeWidth': 10
}.then((polygon: Polygon) => {
...
});
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 =
this.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');
});
});
TileOverlay
@ionic-native/google-maps
TileOverlay
You can generate various 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
});
HtmlInfoWindow
@ionic-native/google-maps
HtmlInfoWindow
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);
});
});
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();
});
});
Geocoding
@ionic-native/google-maps
Geocoding
Geocoding for one address
// Address -> latitude,longitude
this.geocoder.geocode({
"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
Pass locations as array
Get a mvc array first,
then `finish` event is
notified.
Just 1.9 sec!
this.geocoder.geocode({
// US Capital cities
"address": [
"Montgomery, AL, USA", "Juneau, AK, USA", ...
"Madison, WI, USA", "Cheyenne, Wyoming, USA"
]
})
.then((mvcArray: BaseArrayClass<GeocoderResult[]>) => {
});
BaseClass
@ionic-native/google-maps
All classes extend Base class
BaseClass
BaseArrayClass Marker
Circle Polyline Polygon
GroundOverlay TileOverlay MarkerCluster
Map
BaseClass
● set()
● get()
● bindTo()
● trigger()
● on() / addEventListener()
● one() / addEventListenerOnce()
● off()
● empty()
● destroy()
set() and get()
"Hello_changed" event occurs
obj.set(key, value, noNotify?)
obj.get(key)
let myObj: BaseClass = new BaseClass();
myObj.set("hello", "world");
console.log(myObj.get("hello"));
(key)_changed event
let myObj: BaseClass = new BaseClass();
myObj.on("hello_changed").subscribe((params) => {
console.log(params);
});
myObj.set("hello", "world");
myObj.set("hello", "world2");
hello_changed
hello_changed
Status change event
marker.setPosition(...);
marker.setTitle("....");
position_changed
title_changed
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 + "'");
});
});
noNotify option
let myObj: BaseClass = new BaseClass();
myObj.on("hello_changed").subscribe((params) => {
console.log(params);
});
myObj.set("hello", "world", true);
hello_changed
DO NOT
OCCUR
bindTo()
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
"こんにちは" "こんにちは"
sourceObj.bindTo(targetKey, dest, destKey?, noNotify?)
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");
});
});
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
All methods are executed in asynchronously!
this.map.addMarker({
…
})
exec("Map", "loadPlugin",
"Marker");
map.addMarker()
(native code)
.then((marker:Marker) =>
{
});
adding Marker after map.clear()
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().then(() => {
….
});
this.map.clear();
for (let i = 0; i < positions.length; i++) {
this.map.addMarker({
position: positions[i]
}).then((marker: Marker) => {
this.markers.push(marker);
});
}
Command queue
map.clear()
addMarker()addMarker() addMarker() addMarker()
addMarker() addMarker()
addMarker()
addMarker() addMarker() addMarker()
Execute method in synchronous
(Stop all other methods)
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.setCameraZoom()
● map.panBy()
● map.clear()
● map.setCameraTilt()
● map.setCameraBearing()
● map.moveCameraZoomIn()
● map.moveCameraZoomOut()
● map.animateCameraZoomIn()
● map.animateCameraZoomOut()
● map.animateCamera()
● map.moveCamera()
● map.setMyLocationEnabled()
● map.getMyLocation()
● map.remove()
● map.setDiv()
BaseArrayClass
@ionic-native/google-maps
BaseArrayClass
● insertAt()
● getArray()
● getAt()
● setAt()
● removeAt()
● getLength()
● reverse()
● sort()
● indexOf()
● empty()
● push()
● pop()
● map()
● mapAsync()
● forEach()
● forEachAsync()
● filter()
● filterAsync()
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: positions[i]
}).then((marker: Marker) => {
this.markers.push(marker);
});
});
forEachAsync()
0 1 2 3 4
baseArray.forEachAsync(fn).then()
Async task
(i.e. setTimeout())
forEachAsync() baseArray.forEachAsync(fn).then()
let baseArray: BaseArrayClass<ILatLng> = new BaseArrayClass(positions);
baseArray.forEachAsync((position: ILatLng, next:() => void) => {
this.map.addMarker({
position: positions[i]
}).then((marker: Marker) => {
this.markers.push(marker);
next();
});
}.then(() => {
console.log('finish!');
});
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((position: ILatLng, idx: number) => {
return this.markers[idx].getTitle();
});
map() baseArray.map(fn)
0 1 2 3 4
a b c d e
a b c d e
Async task
(i.e. setTimeout())
mapAsync() baseArray.mapAsync(fn).then()
let baseArray: BaseArrayClass<ILatLng> = new BaseArrayClass(positions);
baseArray.mapAsync((position: ILatLng, next: (result: any) => void) => {
this.map.addMarker({
position: positions[i]
}).then(next);
}).then(markers: Marker[]) => {
console.log('finish!');
});
mapAsync() baseArray.mapAsync(fn).then()
0 1 2 3 4
true false true false true
a c e
filter() baseArray.filter(fn)
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';
});
0 1 2 3 4
true false true false true
a c e
Async task
(i.e. setTimeout())
filterAsync() baseArray.filterAsync(fn).then()
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
next(location.category === 'restaurant');
});
}).then(matchedMarkers: Marker[]) => {
console.log('finish');
});
Asynchronous
process
push(), pop()
let baseArray: BaseArrayClass = new BaseArrayClass();
baseArray.push('a');
baseArray.push('b');
baseArray.push('c');
baseArray.pop();
baseArray.pop();
baseArray.pop();
insert_at event
remove_at event
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();
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.
markers[0].trigger('position_changed', null, markers[0].getPosition());
});
baseArray.on('set_at', () => {
this._ngZone.run(() => {
let distanceMeter: number = this.spherical.computeLength(baseArray);
this.distance = (distanceMeter * 0.000621371192).toFixed(2) + " miles";
});
});
});
polyline.getPoints() returns
BaseArrayClass
Calculate the distance
when any markers are dragged
BaseArrayClass example
Plugin repository
https://github.com/mapsplugin/
cordova-plugin-googlemaps
Official documents
https://github.com/mapsplugin/cord
ova-plugin-googlemaps-doc
Code repository
https://github.com/mapsplugin/ionic-
googlemaps-quickdemo
Google Developers Expert of
Google Maps API
Masashi Katsumata
Cordova GoogleMaps plugin
author
&

More Related Content

Similar to @Ionic native/google-maps

Maps API on_mobile_dev_festbangkok
Maps API on_mobile_dev_festbangkokMaps API on_mobile_dev_festbangkok
Maps API on_mobile_dev_festbangkokss318
 
Sirius Web Advanced : Customize and Extend the Platform
Sirius Web Advanced : Customize and Extend the PlatformSirius Web Advanced : Customize and Extend the Platform
Sirius Web Advanced : Customize and Extend the PlatformObeo
 
android level 3
android level 3android level 3
android level 3DevMix
 
Gmaps Railscamp2008
Gmaps Railscamp2008Gmaps Railscamp2008
Gmaps Railscamp2008xilinus
 
Introduction To Google Android (Ft Rohan Bomle)
Introduction To Google Android (Ft Rohan Bomle)Introduction To Google Android (Ft Rohan Bomle)
Introduction To Google Android (Ft Rohan Bomle)Fafadia Tech
 
Android Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NC
Android Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NCAndroid Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NC
Android Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NCJim Tochterman
 
The 2016 Android Developer Toolbox [MOBILIZATION]
The 2016 Android Developer Toolbox [MOBILIZATION]The 2016 Android Developer Toolbox [MOBILIZATION]
The 2016 Android Developer Toolbox [MOBILIZATION]Nilhcem
 
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...mharkus
 
Android L08 - Google Maps and Utilities
Android L08 - Google Maps and UtilitiesAndroid L08 - Google Maps and Utilities
Android L08 - Google Maps and UtilitiesMohammad Shaker
 
GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...
GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...
GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...Bruno Salvatore Belluccia
 
Mobile App Development: Primi passi con NativeScript e Angular 2
Mobile App Development: Primi passi con NativeScript e Angular 2Mobile App Development: Primi passi con NativeScript e Angular 2
Mobile App Development: Primi passi con NativeScript e Angular 2Filippo Matteo Riggio
 
Android MapView and MapActivity
Android MapView and MapActivityAndroid MapView and MapActivity
Android MapView and MapActivityAhsanul Karim
 
Developing AIR for Android with Flash Professional
Developing AIR for Android with Flash ProfessionalDeveloping AIR for Android with Flash Professional
Developing AIR for Android with Flash ProfessionalChris Griffith
 
The Glass Class - Tutorial 4 - GDK-Live Cards
The Glass Class - Tutorial 4 - GDK-Live CardsThe Glass Class - Tutorial 4 - GDK-Live Cards
The Glass Class - Tutorial 4 - GDK-Live CardsGun Lee
 
A tech writer, a map, and an app
A tech writer, a map, and an appA tech writer, a map, and an app
A tech writer, a map, and an appSarah Maddox
 

Similar to @Ionic native/google-maps (20)

Maps API on_mobile_dev_festbangkok
Maps API on_mobile_dev_festbangkokMaps API on_mobile_dev_festbangkok
Maps API on_mobile_dev_festbangkok
 
Sirius Web Advanced : Customize and Extend the Platform
Sirius Web Advanced : Customize and Extend the PlatformSirius Web Advanced : Customize and Extend the Platform
Sirius Web Advanced : Customize and Extend the Platform
 
android level 3
android level 3android level 3
android level 3
 
Gmaps Railscamp2008
Gmaps Railscamp2008Gmaps Railscamp2008
Gmaps Railscamp2008
 
Introduction To Google Android (Ft Rohan Bomle)
Introduction To Google Android (Ft Rohan Bomle)Introduction To Google Android (Ft Rohan Bomle)
Introduction To Google Android (Ft Rohan Bomle)
 
Android Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NC
Android Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NCAndroid Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NC
Android Development w/ ArcGIS Server - Esri Dev Meetup - Charlotte, NC
 
mobl
moblmobl
mobl
 
The 2016 Android Developer Toolbox [MOBILIZATION]
The 2016 Android Developer Toolbox [MOBILIZATION]The 2016 Android Developer Toolbox [MOBILIZATION]
The 2016 Android Developer Toolbox [MOBILIZATION]
 
Google Maps API 101
Google Maps API 101Google Maps API 101
Google Maps API 101
 
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...
GDG GeorgeTown Devfest 2014 Presentation: Android Wear: A Developer's Perspec...
 
Android L08 - Google Maps and Utilities
Android L08 - Google Maps and UtilitiesAndroid L08 - Google Maps and Utilities
Android L08 - Google Maps and Utilities
 
GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...
GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...
GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...
 
Mobile App Development: Primi passi con NativeScript e Angular 2
Mobile App Development: Primi passi con NativeScript e Angular 2Mobile App Development: Primi passi con NativeScript e Angular 2
Mobile App Development: Primi passi con NativeScript e Angular 2
 
Android MapView and MapActivity
Android MapView and MapActivityAndroid MapView and MapActivity
Android MapView and MapActivity
 
Developing AIR for Android with Flash Professional
Developing AIR for Android with Flash ProfessionalDeveloping AIR for Android with Flash Professional
Developing AIR for Android with Flash Professional
 
Android 3
Android 3Android 3
Android 3
 
The Glass Class - Tutorial 4 - GDK-Live Cards
The Glass Class - Tutorial 4 - GDK-Live CardsThe Glass Class - Tutorial 4 - GDK-Live Cards
The Glass Class - Tutorial 4 - GDK-Live Cards
 
Google Maps JS API
Google Maps JS APIGoogle Maps JS API
Google Maps JS API
 
Android classes in mumbai
Android classes in mumbaiAndroid classes in mumbai
Android classes in mumbai
 
A tech writer, a map, and an app
A tech writer, a map, and an appA tech writer, a map, and an app
A tech writer, a map, and an app
 

Recently uploaded

Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessPixlogix Infotech
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 

Recently uploaded (20)

Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 

@Ionic native/google-maps

  • 1. @ionic-native / google-maps Cordova GoogleMaps plugin project Masashi Katsumata
  • 3. @ionic-native/google-maps ● Embed native Google Maps view in your app ● One code for both Android and iOS ● Easy to use ● Faster than Google Maps Javascript API v3 ● Free to use. Apache License v2
  • 4. ・UI components ・View management ・TypeScript -> JS ...etc Your code run on this browser view Bridge between native system and your code!
  • 7. The Map is touchable The side menu is touchable!! The Map is not touchable!
  • 8. Google Map is under the browser!!
  • 9. touch layer (native) Is this on map or browser? Pass the touch event to the map or browser
  • 11. Google Maps API key https://console.developers.google.com/projectselector/apis/library API key
  • 12. Enable Google Maps APIs Enable Both APIs API key
  • 14. Generate an API key This is the API key Restrict your key when you release your app API key
  • 15. Create a project & install plugins $> ionic start myApp sidemenu $> npm install @ionic-native/google-maps @ionic-native/core $> ionic cordova plugin add cordova-plugin-googlemaps --variable API_KEY_FOR_ANDROID=”.....” --variable API_KEY_FOR_IOS=”.....” Please use the latest version anytime! API key Create project
  • 16. app/src/app.module.ts Add this line Add this line API key Create project import { BrowserModule } from '@angular/platform-browser'; ... import { GoogleMaps } from "@ionic-native/google-maps"; @NgModule({ .... providers: [ StatusBar, SplashScreen, GoogleMaps, {provide: ErrorHandler, useClass: IonicErrorHandler} ] }) export class AppModule {}
  • 17. src/pages/home/home.html Add a div (map div) API key Create project HTML & CSS <ion-content padding> <h3>Ionic GoogleMaps Starter</h3> <div id="map_canvas"> <button ion-button (click)="onButtonClick($event)">Start demo</button> </div> </ion-content>
  • 18. src/pages/home/home.scss page-home { #map_canvas { height: 90%; } } Background styles become be transparent by the maps plugin mandatory! You can set the background color through Environment.setBackgroundColor() API key Create project HTML & CSS
  • 19. src/app/app.components.ts API key Create project HTML & CSS Coding export class MyApp { @ViewChild(Nav) nav: Nav; rootPage: any; constructor(public platform: Platform, public statusBar: StatusBar, public splashScreen: SplashScreen) { this.initializeApp(); } initializeApp() { this.platform.ready().then(() => { this.rootPage = HomePage; // Okay, so the platform is ready and our plugins are available. // Here you can do any higher level native things you might need. this.statusBar.styleDefault(); this.splashScreen.hide(); }); } Set the first page after the platform.read() is called
  • 20. If you forget that … ionViewDidLoad() is executed (DOM elements are ready) platform.ready() is executed later (the native plugins are ready to use) Then you get this error message
  • 21. src/pages/home/home.ts API key Create project HTML & CSS Coding import { GoogleMaps, GoogleMap, GoogleMapsEvent } from '@ionic-native/google-maps'; export class HomePage { map: GoogleMap; constructor( public navCtrl: NavController, private googleMaps: GoogleMaps ) { } ionViewDidLoad() { this.loadMap(); }
  • 22. src/pages/home/home.ts loadMap() { // Create a map after the view is ready and the native platform is ready. this.map = this.googleMaps.create('map_canvas'); // Wait the maps plugin is ready until the MAP_READY event this.map.one(GoogleMapsEvent.MAP_READY).then(() => { console.log('map is ready to use.'); }); } API key Create project HTML & CSS Coding
  • 23. Run it!! $> ionic cordova run android API key Create project HTML & CSS Coding Run it!
  • 25. Add a marker this.map.addMarker({ title: 'Ionic', icon: 'blue', animation: 'DROP', position: { lat: 43.0741904, lng: -89.3809802 } }).then((marker: Marker) => { marker.showInfoWindow(); });
  • 26. icon property this.map.addMarker({ title: 'Ionic', icon: 'blue', animation: 'DROP', position: { lat: 43.0741904, lng: -89.3809802 } }).then((marker: Marker) => { marker.showInfoWindow(); }); color name : blue, red, green, yellow .... (157 color names are defined in this plugin) rgb(), rgba() , hsl(), hsla(), #RGB, #RGBA : ./assets/icon.png (jpg, gif, and png) : http(s)://yourserver/icon.png : cdvfile:// …. /icon.png : data:image/png;base64,iVBORw0KGgo...CC : :
  • 27. 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" } ]);
  • 28. Marker events ● MARKER_CLICK ● MARKER_DRAG_START ● MARKER_DRAG ● MARKER_DRAG_END ● INFO_CLICK ● INFO_LONG_CLICK ● INFO_OPEN ● INFO_CLOSE
  • 29. Add event listener Listen the event only one time Listen the event multiple times marker.addEventListenerOnce(GoogleMapsEvent.MARKER_CLICK).then(); // Alias method marker.one(GoogleMapsEvent.MARKER_CLICK).then(); marker.addEventListener(GoogleMapsEvent.MARKER_CLICK).subscribe(); // Alias method marker.on(GoogleMapsEvent.MARKER_CLICK).subscribe();
  • 30. 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();
  • 31. 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"); }); }
  • 33. Polyline let AIR_PORTS = [ HND_AIR_PORT, HNL_AIR_PORT, SFO_AIR_PORT ]; this.map.addPolyline({ points: AIR_PORTS, color: '#AA00FF', width: 10, geodesic: true, 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(); }); }); }); Click event with LatLng (Because this plugin calculates own way)
  • 35. Polygon Just pass ILatLng[] 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} ]; this.map.addPolygon({ 'points':GORYOKAKU_POINTS, 'strokeColor' : '#AA00FF', 'fillColor' : '#00FFAA', 'strokeWidth': 10 }.then((polygon: Polygon) => { ... });
  • 37. 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 = this.spherical.computeDistanceBetween(center, newValue); circle.setRadius(newRadius); }); });
  • 39. 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'); }); });
  • 41. TileOverlay You can generate various 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 });
  • 43. HtmlInfoWindow 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); }); });
  • 45. 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(); }); });
  • 47. Geocoding Geocoding for one address // Address -> latitude,longitude this.geocoder.geocode({ "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(...)
  • 48. Batch geocoding Pass locations as array Get a mvc array first, then `finish` event is notified. Just 1.9 sec! this.geocoder.geocode({ // US Capital cities "address": [ "Montgomery, AL, USA", "Juneau, AK, USA", ... "Madison, WI, USA", "Cheyenne, Wyoming, USA" ] }) .then((mvcArray: BaseArrayClass<GeocoderResult[]>) => { });
  • 50. All classes extend Base class BaseClass BaseArrayClass Marker Circle Polyline Polygon GroundOverlay TileOverlay MarkerCluster Map
  • 51. BaseClass ● set() ● get() ● bindTo() ● trigger() ● on() / addEventListener() ● one() / addEventListenerOnce() ● off() ● empty() ● destroy()
  • 52. set() and get() "Hello_changed" event occurs obj.set(key, value, noNotify?) obj.get(key) let myObj: BaseClass = new BaseClass(); myObj.set("hello", "world"); console.log(myObj.get("hello"));
  • 53. (key)_changed event let myObj: BaseClass = new BaseClass(); myObj.on("hello_changed").subscribe((params) => { console.log(params); }); myObj.set("hello", "world"); myObj.set("hello", "world2"); hello_changed hello_changed
  • 55. 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 + "'"); }); });
  • 56. noNotify option let myObj: BaseClass = new BaseClass(); myObj.on("hello_changed").subscribe((params) => { console.log(params); }); myObj.set("hello", "world", true); hello_changed DO NOT OCCUR
  • 57. bindTo() 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 "こんにちは" "こんにちは" sourceObj.bindTo(targetKey, dest, destKey?, noNotify?)
  • 58. 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"); }); });
  • 59. 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); }
  • 61. All methods are executed in asynchronously! this.map.addMarker({ … }) exec("Map", "loadPlugin", "Marker"); map.addMarker() (native code) .then((marker:Marker) => { });
  • 62. adding Marker after map.clear() this.map.clear(); for (let i = 0; i < positions.length; i++) { this.map.addMarker({ position: positions[i] }).then((marker: Marker) => { this.markers.push(marker); }); }
  • 63. map.clear() is slow... Correct way: this.map.clear().then(() => { …. }); this.map.clear(); for (let i = 0; i < positions.length; i++) { this.map.addMarker({ position: positions[i] }).then((marker: Marker) => { this.markers.push(marker); }); }
  • 64. Command queue map.clear() addMarker()addMarker() addMarker() addMarker() addMarker() addMarker() addMarker() addMarker() addMarker() addMarker() Execute method in synchronous (Stop all other methods) addMarker()addMarker() addMarker() addMarker() addMarker() addMarker() addMarker() addMarker() addMarker() addMarker() Execute 10 methods in parallel at a once
  • 65. Limit 10 is problem sometimes... Sorry, there is no solution currently.
  • 66. synchronous methods ● googleMaps.create() ● map.setCameraZoom() ● map.panBy() ● map.clear() ● map.setCameraTilt() ● map.setCameraBearing() ● map.moveCameraZoomIn() ● map.moveCameraZoomOut() ● map.animateCameraZoomIn() ● map.animateCameraZoomOut() ● map.animateCamera() ● map.moveCamera() ● map.setMyLocationEnabled() ● map.getMyLocation() ● map.remove() ● map.setDiv()
  • 68. BaseArrayClass ● insertAt() ● getArray() ● getAt() ● setAt() ● removeAt() ● getLength() ● reverse() ● sort() ● indexOf() ● empty() ● push() ● pop() ● map() ● mapAsync() ● forEach() ● forEachAsync() ● filter() ● filterAsync()
  • 70. forEach() baseArray.forEach(fn) let baseArray: BaseArrayClass<ILatLng> = new BaseArrayClass(positions); baseArray.forEach((position: ILatLng, idx: number) => { this.map.addMarker({ position: positions[i] }).then((marker: Marker) => { this.markers.push(marker); }); });
  • 71. forEachAsync() 0 1 2 3 4 baseArray.forEachAsync(fn).then() Async task (i.e. setTimeout())
  • 72. forEachAsync() baseArray.forEachAsync(fn).then() let baseArray: BaseArrayClass<ILatLng> = new BaseArrayClass(positions); baseArray.forEachAsync((position: ILatLng, next:() => void) => { this.map.addMarker({ position: positions[i] }).then((marker: Marker) => { this.markers.push(marker); next(); }); }.then(() => { console.log('finish!'); });
  • 73. 0 1 2 3 4 a b c d e a b c d e map() baseArray.map(fn)
  • 74. let baseArray: BaseArrayClass<Marker> = new BaseArrayClass(this.markers); let titles: [] = baseArray.map((position: ILatLng, idx: number) => { return this.markers[idx].getTitle(); }); map() baseArray.map(fn)
  • 75. 0 1 2 3 4 a b c d e a b c d e Async task (i.e. setTimeout()) mapAsync() baseArray.mapAsync(fn).then()
  • 76. let baseArray: BaseArrayClass<ILatLng> = new BaseArrayClass(positions); baseArray.mapAsync((position: ILatLng, next: (result: any) => void) => { this.map.addMarker({ position: positions[i] }).then(next); }).then(markers: Marker[]) => { console.log('finish!'); }); mapAsync() baseArray.mapAsync(fn).then()
  • 77. 0 1 2 3 4 true false true false true a c e filter() baseArray.filter(fn)
  • 78. 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'; });
  • 79. 0 1 2 3 4 true false true false true a c e Async task (i.e. setTimeout()) filterAsync() baseArray.filterAsync(fn).then()
  • 80. 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 next(location.category === 'restaurant'); }); }).then(matchedMarkers: Marker[]) => { console.log('finish'); }); Asynchronous process
  • 81. push(), pop() let baseArray: BaseArrayClass = new BaseArrayClass(); baseArray.push('a'); baseArray.push('b'); baseArray.push('c'); baseArray.pop(); baseArray.pop(); baseArray.pop(); insert_at event remove_at event
  • 82. 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...
  • 83. BaseArrayClass example .then((polyline: Polyline) => { let baseArray: BaseArrayClass<ILatLng> = polyline.getPoints(); 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. markers[0].trigger('position_changed', null, markers[0].getPosition()); }); baseArray.on('set_at', () => { this._ngZone.run(() => { let distanceMeter: number = this.spherical.computeLength(baseArray); this.distance = (distanceMeter * 0.000621371192).toFixed(2) + " miles"; }); }); }); polyline.getPoints() returns BaseArrayClass Calculate the distance when any markers are dragged
  • 85. Plugin repository https://github.com/mapsplugin/ cordova-plugin-googlemaps Official documents https://github.com/mapsplugin/cord ova-plugin-googlemaps-doc Code repository https://github.com/mapsplugin/ionic- googlemaps-quickdemo Google Developers Expert of Google Maps API Masashi Katsumata Cordova GoogleMaps plugin author &