How I make a pointer over the MapView with NativeScript and Angular2? - google-maps

My location with longitude and latitude is working but I need to make a pointer over there, is it possible? I am using NativeScript, Angular2 and NativeScript plugin for Google Maps SDK (nativescript-google-sdk)
file.ts
import { registerElement } from 'nativescript-angular/element-registry';
registerElement("MapView", () => require("nativescript-google-maps-sdk").MapView);
file.xml
<MapView [latitude]="configService.unitPreview.latitude" [longitude]="configService.unitPreview.longitude"
zoom="17" bearing="0"
tilt="0" (mapReady)="OnMapReady"
(markerSelect)="onMarkerSelect"
(cameraChanged)="onCameraChanged">
</MapView>
map_without_pointer
map_with_pointer

You could use addMarker method to add Markers in the map. You could review my example below, where have been shown, how to do that.
app,component.html
<GridLayout>
<MapView (mapReady)="onMapReady($event)" ></MapView>
</GridLayout>
app.com-ponent.ts
import {Component, ElementRef, ViewChild} from '#angular/core';
var mapsModule = require("nativescript-google-maps-sdk");
#Component({
selector: "my-app",
templateUrl: "app.component.html",
})
export class AppComponent {
#ViewChild("MapView") mapView: ElementRef;
constructor(){
}
//Map events
onMapReady = (event) => {
console.log("Map Ready");
var map =event.object;
var marker = new mapsModule.Marker();
marker.position = mapsModule.Position.positionFromLatLng(48.87, 2.35);
marker.title = "Sydney";
marker.snippet = "Australia";
marker.userData = { index : 1};
map.addMarker(marker);
};
}

It is possible show the real traffic like image bellow?
traffic_real_time.png

Related

Trying to Add Markers to Leaflet Map with button click (Using Angular)

I have the following code where I am creating a leaflet map on initial load of the page. I have about four jsons with lat/lon data that I would like to populate the map. What I'm looking for is four buttons that when clicked will add the json data as markers to the map.
What I'm getting is an error indicating the following:
Cannot read properties of undefined (reading 'addLayer').
Map Component:
import { Component, AfterViewInit, OnInit } from '#angular/core';
import { MapPointsService } from './map-points.service';
import * as L from 'leaflet';
#Component({
selector: 'app-map',
templateUrl: './map.component.html',
styleUrls: ['./map.component.css'],
})
export class MapComponent implements AfterViewInit {
private map: L.Map | L.LayerGroup<any> | undefined;
area: any;
markersLayer = new L.LayerGroup();
private initMap(): void {
this.map = L.map('map', {
center: [4.5709, -74.2973],
zoom: 3,
});
this.area = this.map;
const tiles = L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
{
maxZoom: 18,
minZoom: 3,
attribution:
'© OpenStreetMap',
}
);
tiles.addTo(this.map);
}
constructor(private mapService: MapPointsService) {}
ngAfterViewInit(): void {
this.initMap();
// this.mapService.jsonMarkers(this.area);
}
addMarkers(): void {
this.mapService.jsonMarkers(this.area);
}
}
MapService
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
// import { MapComponent } from './map.component';
import * as L from 'leaflet';
#Injectable({
providedIn: 'root',
})
export class MapPointsService {
constructor(private http: HttpClient) {}
jsonMarkers(map: L.Map): void {
this.http
.get('/assets/data/<my_json>.json')
.subscribe((res: any) => {
for (const area of res.<json_item>) {
const lon = are.Longitude;
const lat = are.Latitude;
const marker = L.marker([lat, lon]);
/*if (map.hasLayer(marker)) {
map.removeLayer(marker);
}*/
marker.addTo(map);
// console.log(markers);
}
});
}
}
Info Component that calls function
import { Component, OnInit } from '#angular/core';
import { MapPointsService } from '../map/map-points.service';
import { MapComponent } from '../map/map.component';
import { MatSnackBar } from '#angular/material/snack-bar';
#Component({
selector: 'app-information',
templateUrl: './information.component.html',
styleUrls: ['./information.component.css'],
})
export class InformationComponent implements OnInit {
/**
* showSpinner boolean
*/
showSpinner = false;
constructor(
private _snackBar: MatSnackBar,
private mapService: MapPointsService
) {}
ngOnInit(): void {}
run(msg: string): void {
const snackBarRef = this._snackBar.open('Running ' + msg, 'Close', {
duration: 3000,
});
snackBarRef.afterDismissed().subscribe(() => {
this.showSpinner = false;
});
this.showSpinner = true;
}
mapData() {
let data = new MapComponent(this.mapService);
data.addMarkers();
}
}
Info Html
<button type="button" (click)='mapData()'></button>
If you manually instantiate an Angular component with just the new keyword (let data = new MapComponent(this.mapService)), it will not be mounted anywhere, and in particular its lifecycle methods, like ngAfterViewInit, will not be called.
Then in your case, this.map and this.area remain undefined, leading to your error message.
Since you do not show your templates, it is hard to tell how your components are supposed to be related.
In case your <app-information> (InformationComponent) contains the <app-map> (MapComponent), you can use #ViewChild in InformationComponent to get a reference to the child MapComponent, and from there you can call its addMarkers method.
In case they are in the opposite situation, IIRC you can just request a MapComponent type in InformationComponent constructor, and Angular will inject it from its ancestors tree.
And if they are somehow siblings, then you could manage from a common ancestor:
get a ref to the MapComponent as described first
add an #Output event emitter on InformationComponent that fires when your button is clicked, and in the ancestor you listen to that event, and call the MapComponent.addMarkers method.

Angular - Is it possible to destroy component (not dynamically created)?

I am using Angular 2 google map one of our application. We are loading marker every 5 secs using Sockets. The problem is need to remove previous marker when new marker receive from socket. There is no proper documents in Angular map official site. So thought of destroy components from our app components. And we got all the child components find the following code.
import { Component, OnInit, ViewChild, ViewChildren, QueryList } from '#angular/core';
import { Socket } from 'ng2-socket-io';
import { Marker } from './google-map';
import { SebmGoogleMapMarker } from 'angular2-google-maps/core';
#Component({
selector: 'app-google-map',
templateUrl: './google-map.component.html',
styleUrls: ['./google-map.component.scss'],
providers: [SebmGoogleMapMarker]
})
export class GoogleMapComponent implements OnInit {
public lat: number = 51.678418;
public lng: number = 7.809007;
public markers: Marker[] = [];
#ViewChildren(SebmGoogleMapMarker) SebmGoogleMapMarkers: QueryList<SebmGoogleMapMarker>;
constructor(private socket: Socket) { }
ngOnInit() {
this.socket.on('markers', this.setMarkers);
}
setMarkers = (data: Marker[]) => {
this.removeMarkers();
for (let marker of data) {
var model = new Marker(marker);
this.markers.push(model);
}
}
removeMarkers() {
if (this.SebmGoogleMapMarkers.length > 0) {
this.SebmGoogleMapMarkers.forEach((ele) => {
ele.ngOnDestroy();
});
}
}
}
<div class="col-lg-12">
<sebm-google-map [latitude]="lat" [longitude]="lng">
<sebm-google-map-marker *ngFor="let marker of markers" [latitude]="marker.latitude" [longitude]="marker.longitude">
</sebm-google-map-marker>
</sebm-google-map>
</div>
We got all child components but still reference are there SebmGoogleMapMarkers query list. Is there anyway to destroy component angular way?
Actually here my concern is this.SebmGoogleMapMarkers.length is increasing every 5 sec. what i am feeling is application performance will be reduce.
Solution: I made silly mistake forgot to make marker array empty before pushing.
As far as I know there is no way to destroy a component that was not dynamically added. You can use *ngIf to remove a component though:
<sebm-google-map-markers *ngIf="show">
You can also create your own *ngIf variant that for example includes the logic to remove the component when not needed anymore. Creating such a structural directive is quite simple (https://angular.io/docs/ts/latest/guide/structural-directives.html)

How do you add map markers with the nativescript-google-maps-sdk with Angular 2

I'm trying to use this google maps plugin for NativeScript. I have the map displaying not but I don't see anything in the documentation about adding markers with Angular 2. Does anyone know how to add markers to a map with Angular 2 components?
From the readme here: https://github.com/dapriett/nativescript-google-maps-sdk/blob/master/README.md
/app/map-example.component.html
<GridLayout>
<MapView (mapReady)="onMapReady($event)"></MapView>
</GridLayout>
/app/map-example.component.ts
import {Component, ElementRef, ViewChild} from '#angular/core';
import { MapView, Position, Marker } from 'nativescript-google-maps-sdk';
#Component({
selector: 'map-example-component',
templateUrl: 'map-example.component.html'
})
export class MapExampleComponent {
private mapView: MapView;
//Map events
private onMapReady(args): void {
this.mapView = args.object;
this.addMarker();
}
private addMarker(): void {
console.log("Setting a marker...");
var marker = new Marker();
marker.position = Position.positionFromLatLng(-33.86, 151.20);
marker.title = "Sydney";
marker.snippet = "Australia";
marker.userData = { index : 1};
this.mapView.addMarker(marker);
}
}

Ionic2 google maps image layer

I am building an Ionic2 app where I am using google maps as an orientation map and I need to put an image layer on top of the map. I am trying to put building layout image over the building complex in Google maps.
I found this solution for javascript here, which is exactly what I need: Google maps js API
I am quite new to Ionic2 and Anglular2 and having no luck figuring it out so far.
Any advice appreciated
My code :
import { Component, ViewChild, ElementRef } from '#angular/core';
import { NavController } from 'ionic-angular';
import { Geolocation } from '#ionic-native/geolocation';
declare var google;
#Component({
selector: 'map',
templateUrl: 'map.html'
})
export class MapPage {
#ViewChild('map') mapElement: ElementRef;
map: any;
lat : any ;
lng : any ;
constructor(public navCtrl: NavController, public geolocation: Geolocation) {
this.getGeoLocation();
}
initializeMap() {
var minZoomLevel = 17;
let mapOptions =
{
zoom: minZoomLevel,
center: new google.maps.LatLng(lat, lng),
mapTypeId: google.maps.MapTypeId.ROADMAP,
}
this.map = new google.maps.Map(this.mapElement.nativeElement, mapOptions);
}
getGeoLocation(){
this.geolocation.getCurrentPosition().then((position) => {
this.lat = position.coords.latitude;
this.lng = position.coords.longitude;
this.initializeMap();
}, (err) => {
console.log(err);
});
}
Well, apparently it was easier than I thought. You just define image boundaries and create an instance of an overlay and then add it to the map like this...
var oldBuilding = {
north: 53.27959,
west: -9.01287,
south: 53.278038,
east: -9.00876
};
this.oldBuildingOverLay = new google.maps.GroundOverlay('../assets/Map.png', oldBuilding);
this.oldBuildingOverLay.setMap(this.map);
Declare oldBuildingOverlay: any; and you're up and running.

angular2-google-maps autocomplete not working

I am trying to add autocomplete to my project with angular2-google-maps. I add AgmCoreModule.forRoot (with libraries: 'places') in my AppModule and then added the autocomplete code in my component. Still I get "Cannot read property 'Autocomplete' of undefined" error. I tried checking the value of global var google, and google.map does not contain 'places' field. I am relatively new to angular2, so would need some help to understand what I am missing. My code is
in AppModule
import { AgmCoreModule } from 'angular2-google-maps/core';
#NgModule({
bootstrap: [ App ],
declarations: [
App,
ErrorComponent,
],
imports: [ // import Angular's modules
AgmCoreModule.forRoot({
apiKey: '[API_KEY_REDACTED]',
libraries: ["places"]
}),
BrowserModule,
FormsModule,
ReactiveFormsModule,
HttpModule,
TranslateModule.forRoot(),
RouterModule.forRoot(ROUTES, { useHash: true })
],
providers: [ // expose our Services and Providers into Angular's dependency injection
ENV_PROVIDERS,
APP_PROVIDERS,
]
})
export class AppModule {
In AppComponent:
import {MapsAPILoader} from 'angular2-google-maps/core';
import { NgZone } from '#angular/core';
declare var google: any;
export class EventInfoTab {
#ViewChild('gmap') gmap:any;
constructor(
private _loader: MapsAPILoader,
private zone : NgZone,
)
ngAfterViewInit(): void {
this._loader.load().then(() => {
let address = document.getElementById("location");
console.log("google", google);
let autocomplete = new google.maps.places.Autocomplete(address, {});
console.log ("autocomplete",autocomplete);
google.maps.event.addListener(autocomplete, 'place_changed', () => {
this.zone.run(() => {
console.log ("autocomplete place_changed",autocomplete);
var place = autocomplete.getPlace();
this.lat = place.geometry.location.lat();
this.lng = place.geometry.location.lng();
//alert(JSON.stringify(place));
this.markers[0] ={
lat: this.lat,
lng: this.lng,
label: 'x',
draggable: false
};
});
});
});....
So, I was able to make it work. I was trying to include the map with autocomplete in a feature component, after routing from the main component. I removed the code
'AgmCoreModule.forRoot({
apiKey: '[API_KEY_REDACTED]',
libraries: ["places"]
}),'
from app module.ts and added it in the feature's module.ts imports and it worked.
Since Pooja got hers working, and I had already completed a working example of Angular2 + angular2-google-maps + Autocomplete for her, I thought I'd add the code here to help future developers looking for something similar.
import {
Component,
NgModule,
OnInit,
NgZone
} from '#angular/core';
import {
BrowserModule
} from '#angular/platform-browser';
import {
AgmCoreModule,
MapsAPILoader
} from 'angular2-google-maps/core';
declare var google: any;
#Component({
selector: 'my-app',
styles: [`
.sebm-google-map-container {
height: 300px;
}
`],
template: `
<sebm-google-map
[latitude]="lat"
[longitude]="lng"
[zoom]="zoom"
[disableDefaultUI]="false"
[zoomControl]="true">
<sebm-google-map-marker
*ngFor="let m of markers; let i = index"
(markerClick)="clickedMarker(m.label, i)"
[latitude]="m.lat"
[longitude]="m.lng"
[label]="m.label"
[markerDraggable]="m.draggable"
(dragEnd)="markerDragEnd(m, $event)">
<sebm-google-map-info-window>
<strong>InfoWindow content</strong>
</sebm-google-map-info-window>
</sebm-google-map-marker>
</sebm-google-map>
<input type="text" id="autocompleteInput">
`})
export class App implements OnInit {
constructor(
private _loader: MapsAPILoader,
private _zone: NgZone) {
}
ngOnInit(): void {
this.autocomplete();
}
autocomplete() {
this._loader.load().then(() => {
var autocomplete = new google.maps.places.Autocomplete(document.getElementById("autocompleteInput"), {});
google.maps.event.addListener(autocomplete, 'place_changed', () => {
this._zone.run(() => {
var place = autocomplete.getPlace();
this.markers.push({
lat: place.geometry.location.lat(),
lng: place.geometry.location.lng(),
label: place.name,
});
this.lat = place.geometry.location.lat();
this.lng = place.geometry.location.lng();
console.log(place);
});
});
});
}
// google maps zoom level
zoom: number = 8;
// initial center position for the map
lat: number = 51.673858;
lng: number = 7.815982;
clickedMarker(label: string, index: number) {
console.log(`clicked the marker: ${label || index}`)
}
mapClicked($event: MouseEvent) {
this.markers.push({
lat: $event.coords.lat,
lng: $event.coords.lng
});
}
markerDragEnd(m: marker, $event: MouseEvent) {
console.log('dragEnd', m, $event);
}
markers: marker[] = [];
}
// just an interface for type safety.
interface marker {
lat: number;
lng: number;
label?: string;
draggable: boolean;
}
#NgModule({
imports: [
BrowserModule,
AgmCoreModule.forRoot({
libraries: ['places']
})
],
declarations: [ App ],
bootstrap: [ App ]
})
export class AppModule {}
Working Plnkr
4/17/2017 UPDATE
In version 1.0.0-beta.0 - green-zebra, the AGM team released a breaking change with the naming of their components which will require an update to your template file as follows:
<agm-map
[latitude]="lat"
[longitude]="lng"
[zoom]="zoom"
[disableDefaultUI]="false"
[zoomControl]="true">
<agm-marker
*ngFor="let m of markers; let i = index"
(markerClick)="clickedMarker(m.label, i)"
[latitude]="m.lat"
[longitude]="m.lng"
[label]="m.label"
[markerDraggable]="m.draggable"
(dragEnd)="markerDragEnd(m, $event)">
<agm-info-window>
<strong>InfoWindow content</strong>
</agm-info-window>
</agm-marker>
</agm-map>
<input type="text" id="autocompleteInput">
An updated version of the above plnkr/code can be found in the following GitHub repo.
I also have the same issue, but different cause. I use the map inside modal (pop-up)
let address = document.getElementById("location");
let autocomplete = new google.maps.places.Autocomplete(address, {});
In my case the above code run inside ngOnInit, the problem is the text input element is still not created.
You need to put the autocomplete code inside a function which runs each time the elements are created. I tried ngAfterViewInit, but didn't work