Update google marker with watchposition in ionic - ionic-framework

I am creating a map to track user position, i am using #geolocation plugin and showing map using:
<script src="https://maps.googleapis.com/maps/api/js?key=API_KEYscript>
Currently marker is being displayed and on watchposition marker is placing multiple times and isn’t removing last placed marker.
import { Component, ViewChild, ElementRef } from '#angular/core';
import { Geolocation, GeolocationOptions, Geoposition, PositionError } from '#ionic-native/geolocation';
declare var google;
#Component({
selector: 'app-tab1',
templateUrl: 'tab1.page.html',
styleUrls: ['tab1.page.scss']
})
export class Tab1Page {
geolocation = Geolocation;
options: GeolocationOptions;
currentPos: Geoposition;
#ViewChild('map', { static: false }) mapElement: ElementRef;
map: any;
constructor() { }
ionViewDidEnter() {
this.getUserPosition();
}
getUserPosition() {
this.options = {
enableHighAccuracy: false
};
//get location
this.geolocation.getCurrentPosition(this.options).then((pos: Geoposition) => {
this.currentPos = pos;
console.log(pos);
//add map
let latLng = new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude);
let mapOptions = {
center: latLng,
zoom: 18,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
this.map = new google.maps.Map(this.mapElement.nativeElement, mapOptions);
this.addMarker(latLng);
}, (err: PositionError) => {
console.log("error : " + err.message);
})
let subscription = this.geolocation.watchPosition().subscribe(position =>{
let userPosition = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
this.addMarker(userPosition);
})
}
addMarker(position) {
let marker = new google.maps.Marker({
map: this.map,
animation: google.maps.Animation.DROP,
position: position
});
let content = "<p>This is your current position !</p>";
let infoWindow = new google.maps.InfoWindow({
content: content
});
google.maps.event.addListener(marker, 'click', () => {
infoWindow.open(this.map, marker);
});
}
}
I want to remove last marker before placing another one.
Thank you.

Related

react-leaflet search plugin not working. Can anyone help me out with this

I tried to implement react-leaflet search from https://github.com/tumerorkun/react-leaflet-search but, it didn't worked.
following is my code (without including react-leaflet search). Can anyone help me with it.
Hi, I tried to implement react-leaflet search from https://github.com/tumerorkun/react-leaflet-search but, it didn't worked.
following is my code (without including react-leaflet search). Can anyone help me with it.
import React from "react";
import L from "leaflet";
import 'leaflet-timedimension/dist/leaflet.timedimension.src';
import omnivore from '#mapbox/leaflet-omnivore';
import { Map, Marker, Popup } from 'react-leaflet';
import { ReactLeafletSearch } from 'react-leaflet-search';
// import * as countries from './data/map.geojson';
const config = {};
config.default = {
center: [51.505,-0.09],
zoomControl: true,
zoom: 4,
maxZoom: 19,
minZoom: 11,
scrollWheel: false,
legends: true,
infoControl: true,
attributionControl: true
};
config.tdOptions = {
timeInterval: "2018-09-30/2018-10-30",
period: "PT1H",
};
// ===== Example data sources
config.wmsOne = {
url: "https://demo.boundlessgeo.com/geoserver/ows",
options: { layers: 'nasa:bluemarble', transparent: true },
attribution: "&copy <a href="http://osm.org/copyright">CHANGE THIS</a> contributors",
};
config.wmsTwo = {
url: "https://demo.boundlessgeo.com/geoserver/ows",
options: { layers: 'ne:ne', transparent: true },
attribution: "&copy <a href="http://osm.org/copyright">CHANGE THIS</a> contributors",
};
config.osmLayer = {
url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
params: {
minZoom: 11,
attribution: "&copy <a href="http://osm.org/copyright">CHANGE THIS</a> contributors",
id: '',
accessToken: ''
}
};
// ===== END Example data sources
export default class LeafletMap extends React.Component {
constructor() {
super();
this.state = {
lat: config.default.center[0],
lng: config.default.center[1],
zoom: config.default.zoom,
toggleActive: true,
timeInterval: config.tdOptions.timeInterval,
period: config.tdOptions.period,
gpxLayer: null,
gpxTimeLayer: null,
};
this.initMap = this.initMap.bind(this);
this.initTimeDimension = this.initTimeDimension.bind(this);
this.onClick = this.onClick.bind(this); // Necessary?
}
// Executed when component is mounted Leaflet-React MAP component
componentDidMount() {
this.initMap();
// this.initTimeDimension(); // TODO: MAKE WORK GOOD!
}
initMap() {
// Usual Leaflet way, but we're using react-leaflet's <Map> component instead
/*this.map = new L.map("root", {
center: [this.state.lat, this.state.lng],
zoom: config.params.zoom,
timeDimension: true
});*/
console.log("### Initializing Leaflet map");
// Tile layer(s)
const tileLayerA =
L.tileLayer.wms(config.wmsOne.url, config.wmsOne.options);
const tileLayerB =
L.tileLayer.wms(config.wmsTwo.url, config.wmsTwo.options);
const tileLayerC = L.tileLayer.wms(config.osmLayer.url)
.addTo(this.map.leafletElement);
// const countriesLayer = L.geoJson(countries, {});
// Add controls for toggling layers
L.control.layers({
"OSM Layer": tileLayerC,
"Layer Two": tileLayerA,
"Layer One": tileLayerB
}).addTo(this.map.leafletElement);
}
// TODO: Make work!
initTimeDimension() {
console.log("### Init Leaflet TimeDimension");
let gpxTl = L.timeDimension.layer.geoJson(this.state.gpxLayer, {
updateTimeDimension: true,
addlastPoint: true,
waitForReady: true
});
this.setState({gpxLayer: omnivore.gpx('public/running_mallorca.gpx')});
this.setState({gpxTimeLayer: gpxTl});
// TimeDimension layer(s)
const td = new L.timeDimension({
period: "PT5M",
});
this.map.timeDimension = td;
//Player -> Component to animate a map with a TimeDimension, changing the time periodically.
let player = new L.TimeDimension.Player({
transitionTime: 100,
loop: false,
startOver:true
}, td);
L.control.timeDimension({
player: player,
}).addTo(this.map.leafletElement);
// Add timedimension from GPX data
new L.timeDimension.layer.geoJson(this.state.tdData, {
updateTimeDimension: true,
addlastPoint: true,
waitForReady: true
}).addTo(this.map.leafletElement);
}
onClick = () => {
this.setState({
toggleActive: !this.state.toggleActive,
});
console.log('CLICKED MAP');
// this.map.leafletElement.fitBounds(this.state.tdData);
};
render() {
const position = [this.state.lat, this.state.lng];
const timeDimensionOptions = {
timeInterval: this.state.timeInterval,
period: this.state.period
};
return (
<React.StrictMode>
<Map
center={position}
zoom={this.state.zoom}
onClick={this.onClick}
timeDimension={true}
timeDimensionOptions={timeDimensionOptions}
timeDimensionControl={true}
ref={(ref) => { this.map = ref; }}>
{/*<TileLayer
attribution={config.wmsOne.attribution}
url={config.wmsOne.url}
/>*/}
{/*<WMSTileLayer
layers={this.state.toggleActive ? 'nasa:bluemarble' : 'ne:ne'}
url="https://demo.boundlessgeo.com/geoserver/ows" />*/}
<Marker position={position}>
<Popup>
A pretty CSS3 popup (react-leaflet component). <br />Easily customizable.
</Popup>
</Marker>
</Map>
</React.StrictMode>
);
} // END of render()
}
Use this :
import { SearchControl } from 'react-leaflet-search';
It works, although it's not on the Documentation
Can you post a jsfiddle or codepen demonstrating the problem?
Also... incidentally the way you are adding controls and layers to the map is not recommended by react-leaflet.
new L.timeDimension.layer.geoJson(this.state.tdData, {...}).addTo(this.map.leafletElement);
is imperative. Prefer declarative rendering like
import { Map, TileLayer, GeoJSON } from 'react-leaflet';
<Map>
<TileLayer>
<GeoJSON>
</Map>

IONIC 2 - Cannot retrieve array inside ionViewDidLoad()

I want to retrieve places coordinates from restApi and display them on the map.
I got error : Cannot read property 'length' of undefined
Please help me !
I want you to tell me how i can get my data in order to add multiple markers.
This is my portion of code
import { Component, ViewChild, ElementRef } from '#angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { Geolocation } from '#ionic-native/geolocation';
import { RestProvider } from '../../providers/rest/rest';
declare var google;
#Component({
selector: 'page-localisation',
templateUrl: 'localisation.html',
})
export class LocalisationPage {
#ViewChild('map') mapElement: ElementRef;
map: any;
places: Array<any>;
errorMessage : string;
constructor(public navCtrl: NavController, public navParams: NavParams, public geolocation: Geolocation, public rest: RestProvider) {
}
ionViewDidLoad(){
this.loadMap();
this.getPlaces();
this.addPlacesToMap()
console.log("Length : " + this.places.length) ; //Error Cannot read property 'length' of undefined
}
getPlaces() {
this.rest.getPlaces().subscribe(
places => this.places = places,
error => this.errorMessage = <any>error
);
}
loadMap(){
let latLng = new google.maps.LatLng(-4.066548, 5.356315);
let mapOptions = {
center: latLng,
zoom: 15,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
this.map = new google.maps.Map(this.mapElement.nativeElement, mapOptions);
}
addPlacesToMap(){
//...
}
addInfoWindow(marker, content){
let infoWindow = new google.maps.InfoWindow({
});
content: content
google.maps.event.addListener(marker, 'click', () => {
infoWindow.open(this.map, marker);
});
}
}
ionViewDidLoad is launched before "this.rest.getPlaces().subscribe" is finished... So your variable "places" is NULL
Change getPlaces to a Promise
async getPlaces() {
places = await this.rest.getPlaces() ;
return places
}
Then in ionViewDidLoad
ionViewDidLoad(){
var that = this ;
this.loadMap();
this.getPlaces().then((places)=>{
that.places = places;
console.log("Length : " + that.places.length) ;
});
this.addPlacesToMap()
}

Ionic DevApp: Google maps not showing

I have used JavaScript SDK to display map.
It's working on the browser but when I open it on dev app, the page shows the blank page.
ionViewDidLoad(){
this.loadMap();
}
loadMap(){
this.geolocation.getCurrentPosition().then((position) => {
let latLng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
let mapOptions = {
center: latLng,
zoom: 15,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
this.map = new google.maps.Map(this.mapElement.nativeElement, mapOptions);
}, (err) => {
console.log(err);
});
}
Try to add locationOption
let locationOptions = { timeout: 30000, enableHighAccuracy: true };
and pass to getCurrentPosition like this
this.geolocation.getCurrentPosition(locationOptions).then((p‌​osition) => {

How can I add my current location to Firebase?

In my Ionic 2 application, I'm able to see my current location on the map, but how can I add the location (longtitude and latitude) to Firebase?
initMap(): Promise<any> {
this.mapInitialised = true;
return new Promise((resolve) => {
Geolocation.getCurrentPosition().then((position) => {
let latLng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
//let latLng = new google.maps.LatLng(40.713744, -74.009056);
let mapOptions = {
center: latLng,
zoom: 15,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
this.map = new google.maps.Map(this.mapElement, mapOptions);
resolve(true);
google.maps.event.addListener(this.map, 'click', (event) => {
this.clearMarkers();
let geocoder = new google.maps.Geocoder;
let infowindow = new google.maps.InfoWindow;
let distanceToYou = this.getDistanceBetweenPoints(
event.latLng,
position,
'miles'
).toFixed(2);
this.geocodeLatLng(event.latLng,geocoder,infowindow,distanceToYou);
});
});
});
}
I'm able to get the current position of me and if I double click the map I can see the distance between me and the marker.
Yes it's possible. But since double clicking a map zooms it, i'll use press. But it would be better if you set a button on a info window with a "save location" text or something like this to call the saving function.
YOUR HTML
<div #mapID (press)="saveLocation()">
YOUR .TS
import * as firebase from 'firebase';
public lat;
public long;
initMap(): Promise<any> {
this.mapInitialised = true;
return new Promise((resolve) => {
Geolocation.getCurrentPosition().then((position) => {
this.lat = position.coords.latitude;
this.long = position.coords.longitude;
// YOUR CODE CONTINUES HERE...
});
});
});
saveLocation(){
firebase.database().ref('PATH/YOU/WANT/TO/SAVE').update({
lat: this.lat,
long: this.long
}).then(res =>{
// THE LOCATION IS SAVED, DO YOUR STUFF
})
}
Like this you can save you location, use update() instead of set() so you don't subscribe other data.
If you want to retrieve that data just use firebase.database().ref('PATH/YOU'VE/SAVED').once('value', snapshot =>{ // CODE });
Hope it helps

Leafletjs: How to have new marker in first click then update the latlng of marker in second click

I have list of markers that want to render in the map, but I want it one by one. In first click I want to make new marker. Then when I click to another location, I want my marker to just move to the new latLng not to create another marker. Here is my code:
function (licon, coord, data) {
var self = jQuery(this);
var map = self.data("map");
var latlng = new L.LatLng(coord[0], coord[1]);
//Create Marker
if (licon) {
var leafIcon = L.icon(licon);
console.log(typeof (marker));
if (typeof (marker) === 'undefined') {
var marker = L.marker(latlng, {
icon: leafIcon,
"markerData": data,
draggable: true
});
} else {
console.log('not undefined');
map.removeLayer(marker);
marker = L.marker(latlng, {
icon: leafIcon,
"markerData": data,
draggable: true
});
}
} else {
var marker = L.marker(latlng, {
"markerData": data,
draggable: true
});
}
marker.addTo(map);
return marker;
}
A quick example of the result: http://jsfiddle.net/ve2huzxw/43/
var currentMarker;
map.on("click", function (event) {
if (currentMarker) {
currentMarker.setLatLng(event.latlng);
return;
}
currentMarker = L.marker(event.latlng, {
draggable: true
}).addTo(map).on("click", function () {
event.originalEvent.stopPropagation();
});
});
document.getElementById("done").addEventListener("click", function () {
currentMarker = null;
});
You can also add a smooth transition to show the marker moving to the new position:
if (currentMarker) {
currentMarker._icon.style.transition = "transform 0.3s ease-out";
currentMarker._shadow.style.transition = "transform 0.3s ease-out";
currentMarker.setLatLng(event.latlng);
setTimeout(function () {
currentMarker._icon.style.transition = null;
currentMarker._shadow.style.transition = null;
}, 300);
return;
}
a slightly more consolidated solution some years later.
var currentMarker;
map2.on('click', function(e) {
if (currentMarker){
currentMarker.setLatLng(e.latlng)
} else {
currentMarker = new L.marker(e.latlng).addTo(map2);
};
//console.log('lat, lon: ', e.latlng.lat, e.latlng.lng);
});
leaflet now defaults to smoothly dragging the point over to the new coords.