Update marker position json Leaflet and WebGLEarth - javascript

This question is related to this question: Updating Leaflet Marker Position Every x Seconds with JSON. Only I want to project the map created with Leaflet onto a 3D globe with WebGLEarth. Normally you can combine Leaflet and WebGLEarth by replacing L.map, L.marker and so on with WE.map, WE.marker in your original Leaflet code.
I would like to have the current location of the International Space Station projected on my 3D globe, so I replaced the L.marker in the update_position function of this code...
var cloudmadeUrl = 'http://{s}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg';
var subDomains = ['otile1','otile2','otile3','otile4'];
var cloudmade = new L.TileLayer(cloudmadeUrl, {maxZoom: 11, subdomains: subDomains});
var map = new L.Map('map', {layers : [cloudmade]}).fitWorld();
var iss;
function update_position() {
$.getJSON('http://open-notify-api.herokuapp.com/iss-now.json?callback=?', function(data) {
console.log(data);
var latitude = data["iss_position"]["latitude"];
var longitude = data["iss_position"]["longitude"];
if (!iss) {
iss = L.marker([latitude,longitude]).bindPopup("I am the ISS").addTo(map);
}
iss.setLatLng([latitude,longitude]).update();
setTimeout(update_position, 1000);
});
}
update_position();
DEMO
...by WE.marker. Unfortunately, the updating of the position doesn't work anymore on my 3D globe, whereas it did work on the 2D map.
I tried adding
setInterval(update_position,2000);
just above update_position();, then the marker gets updated a few times (~5) and then suddenly stops. If I interact with my mouse on the globe by panning, the marker gets updated to its current position and gets updated a few times afterwards, and eventually stops again.
Main Question:
Does anyone know how to fix this so that I have a continuous marker update?
Additional Question:
Ideally I would like the International Space Station track to look like https://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=CZML.html&label=Showcases, with a colored path the station travelled in its last orbit around the earth. Any tips on how to do this?
Thanks in advance!
[Edit 23-1-2015:
I managed to update it continuously by making a new variable for iis, namely iis2. Why this works is not clear to my. Unfortunately, all 'old' markerpositions don't dissapear, so I get a blurred marker track.
var iss;
var iis2;
function update_position() {
$.getJSON('http://open-notify-api.herokuapp.com/iss-now.json?callback=?', function(data) {
console.log(data);
var latitude = data["iss_position"]["latitude"];
var longitude = data["iss_position"]["longitude"];
if (!iss) {
iss2 = WE.marker([latitude,longitude]).bindPopup("I am the ISS").addTo(map);
}
iss2.setLatLng([latitude,longitude]).update();
});
}
update_position();
setInterval(update_position,1000);
]

remove the marker
var iss;
var iis2;
function update_position() {
$.getJSON('http://open-notify-api.herokuapp.com/iss-now.json?callback=?', function(data) {
console.log(data);
map.removeLayer(iss2);
var latitude = data["iss_position"]["latitude"];
var longitude = data["iss_position"]["longitude"];
if (!iss) {
iss2 = WE.marker([latitude,longitude]).bindPopup("I am the ISS").addTo(map);
}
iss2.setLatLng([latitude,longitude]).update();
});
}
update_position();
setInterval(update_position,1000);

Related

Javascript leaflet map to toggle "Show Your Location"

I have a leaflet map that displays the area around where the person currently is (currentlocation), and typically I want the map to 'follow' the person as they travel. I am using a mymap.panTo command for this. This much is working fine. It updates the map every 5 seconds and pans to centre on the current person perfectly.
Occasionally though the person may want to scroll the map further afield to see something. This works ... until the 5 second counter kicks in and pans the map back to their location again. Annoying.
I have seen on various map apps a button/toggle on the map that the person can click on to stop the map following them. In fact usually it turns off if the map is shifted manually and then they'd click the toggle to pan back to their current location. Please see the image attached of a google map highlighting what they call a "Show Your Location" button. That's what I want.
But how is this done? Is this some sort of custom leaflet control that I cannot find? Or is it done fully programmatically somehow (and any sample code snippets?).
any help appreciated.
Below is the bit of code I use to display my map.
var streetmap = L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
attribution: 'Map data © OpenStreetMap contributors, Imagery © Mapbox',
id: 'mapbox/streets-v11',
accessToken: 'token code here' //redacted token
}),
satellite = L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
attribution: 'Map data © OpenStreetMap contributors, Imagery © Mapbox',
id: 'mapbox/satellite-v9',
accessToken: 'token code here' //redacted token });
var baseMaps = {
"Streetmap": streetmap,
"Satellite": satellite
};
var mymap = L.map('mapid', {
center: [latitude,longitude],
zoom: 17,
layers: [streetmap] //default layer
});
var personicon = L.icon({
iconUrl: '/js/personicon.png',
iconSize: [20, 20]
});
var playerLoc = new L.marker([latitude,longitude], {icon: personicon}) // set player location marker as a declared variable but don't put it on the map yet
elsewhere I have code to start the map (once variables are populated) and then keep updating location
const interval = setInterval(function() {
if (is_running) { // we need to know that there is data populated before showing or updating the map with it
if (!map_started) { //start the map only once
L.control.layers(baseMaps).addTo(mymap); //show choice of layer views
L.control.scale().addTo(mymap); //show scale bar
console.log("Create current player marker:",MYID,latitude,longitude);
playerLoc.setLatLng([latitude,longitude]).addTo(mymap).bindPopup(MYID); //update current player marker, and now show it on the map
map_started=true;
}; //start the map only once
updatemap(); // for current player location and circle colour.
}; //update only if is_running
mymap.invalidateSize(); //reset map view
}, 5000); // update map every 5 seconds
function updatemap() { // Update the current player location on map
playerLoc.setLatLng([latitude,longitude]); //update current player marker instead of creating new ones
mymap.panTo([latitude,longitude]); // pan the map to follow the player (TODO: Can we toggle pan mode?)
}; // end updatemap
this code all works fine. the mymap.panTo([latitude,longitude]); line is what needs to be wrapped in a condition "If pan is allowed, then do mymap.panTo([latitude,longitude]);" But surely there's a standard leaflet control or approach to this? I see this thing all the time elsewhere
You need to listen on the movestart event, to detect if the user moves the map. But this event is also triggered from the panTo function, so you need a flag to indicate if movestart is fired by interval or by the user.
var currentAutoMove = false; // needed to check in `movestart` event-listener if moved from interval or by user
var pauseAutoMove = false; // if true -> Stops moving map
var latitude,longitude;
setInterval(()=>{
latitude = playerLoc.getLatLng().lat + 0.001;
longitude = playerLoc.getLatLng().lng + 0.001;
updatemap();
}, 1000)
function updatemap() { // Update the current player location on map
playerLoc.setLatLng([latitude,longitude]);
if(!pauseAutoMove){
currentAutoMove = true; // Set flag, that currently map is moved by interval
map.panTo([latitude,longitude]);
currentAutoMove = false; // Remove flag, that currently map is moved by interval
}
}
map.on('movestart',(e)=>{
console.log(e, currentAutoMove);
if(!currentAutoMove){ // Check if map is moved by interval or by user
pauseAutoMove = true; // set flag, to stop moving map
}
})
// Start auto move again, if button clicked
L.DomEvent.on(document.getElementById('toPos'),'click',(e)=>{
pauseAutoMove = false; // reset flag, to stop moving map -> start moving map
map.panTo([latitude,longitude]);
})
To create a Control / button to start auto move you only need to search in Google there are many examples, else you can use L.easybutton.
Demo: https://jsfiddle.net/falkedesign/8akw3ust/
With much thanks to Falke Design I have used the suggestions in the answer above. My code now looks like this for the button I wanted:
var panbtn = L.easyButton({
states: [{
stateName: 'pauseAutoMove',
icon: 'fa-sign-in fa-lg',
title: 'Centre display at current Player', //Tooltip
onClick: function(btn, map) {
console.log("AutoMoveButton pressed");
panbtn.state('AutoMove');
mymap.panTo([latitude,longitude]);
}
}, {
stateName: 'AutoMove',
icon: 'fa-crosshairs fa-lg',
}]
}).addTo(mymap);
mymap.on("zoomstart", function (e) { currentAutoMove = true }); //Set flag, that currently map is moved by a zoom command
mymap.on("zoomend", function (e) { currentAutoMove = false }); //Remove flag again
mymap.on('movestart',(e)=>{ //Check if map is being moved
if(!currentAutoMove){ //ignore if it was a natural PlayerLoc Auto update
pauseAutoMove = true; //set flag to stop Auto moving map
console.log("Map moved");
panbtn.state('pauseAutoMove'); //change button style to remove crosshairs
}
});
and inside the updatemap function the code:
if(!pauseAutoMove){ //pan the map to follow the player unless it is on pause
currentAutoMove = true; //Set flag, that currently map is moved by a normal PlayerLoc Auto update
mymap.panTo([latitude,longitude]);
currentAutoMove = false; //Remove flag again
};
much thanks.

leaflet route360 using as input point geojson layer?

hello I have read this examples about leaflet route 360 services.
is very interests but that examples work with static coordinates,my question is how to can use this services using some point GeoJSON layer ?
my GeoJSON layer example:
coords = [];
var points = new L.GeoJSON.AJAX("{% url 'mylayer' %}",{
onEachFeature:function (feature,layer) {
coords.push(feature.geometry.coordinates.reverse());
layer.on('click', function (e) {
var field1=document.getElementById('f1');
field1.innerHTML=e.target.feature.properties.name;
});
layer.bindPopup(feature.properties.name.toString())
}
});
points.addTo(map);
leaflet route 360 example :
<script>
// define a pair of coordinates, where the map should be centered
// and should serve a the source for polygonization
var latlon = [52.51, 13.37];
// add the map and set the initial center to berlin
var map = L.map('map').setView(latlon, 14);
map.attributionControl.addAttribution("ÖPNV Daten © <a href='https://www.vbb.de/de/index.html' target='_blank'>VBB</a>");
// initialise the base map
r360.basemap({ style: 'basic', apikey: '__your-route360-api-key__' }).addTo(map);
// create the marker and add it to the map
var marker = L.marker((latlon)).addTo(map);
// create the layer to add the polygons
var polygonLayer = r360.leafletPolygonLayer().addTo(map);
// you need to define some options for the polygon service
// for more travel options check out the other tutorials
var travelOptions = r360.travelOptions();
// please contact us and request your own key if you don't already have one
travelOptions.setServiceKey('__your-route360-api-key__');
// set the service url for your area
travelOptions.setServiceUrl('https://service.route360.net/germany/');
// we only have one source which is the marker we just added
travelOptions.addSource(marker);
// we want to have polygons for 10 to 30 minutes
travelOptions.setTravelTimes([600, 1200, 1800]);
// go by foot
travelOptions.setTravelType('walk');
// call the r360°- service
r360.PolygonService.getTravelTimePolygons(travelOptions, function(polygons){
// add the returned polygons to the polygon layer
// and zoom the map to fit the polygons perfectly
polygonLayer.clearAndAddLayers(polygons, true);
});
</script>

Nearest Street View Photo to Coordinates

I'm working on proof-of-concept application using Google Maps V3 API. I have a database with a list of all cities and their center points in (lat,lng) format. When I open a random city from the database, the map is centered to the center point and switches to Street View view.
The problem is: sometimes there are user submitted photos and no "walk" feature in this case. Here is an example of such a photo which is also a part of Street View layer:
Is there a way to avoid these user photos and are they different from Google Maps API standpoint from the real photos made by Google drivers with "walk" feature? I need a way to skip to the next nearest point with "proper" Street View photo from a Google car.
Another question: is there a way/algorithm to find the nearest street view point to the coordinates given?
Here is the current code snippet:
var point = new google.maps.LatLng(data[0].lat, data[0].lng);
var webService = new google.maps.StreetViewService();
var checkaround = 5000;
webService.getPanoramaByLocation(point,checkaround ,function(panoData) {
if(panoData){
if(panoData.location){
if(panoData.location.latLng){
window.map.setCenter(panoData.location.latLng);
window.map.setZoom(14);
var panoramaOptions = {
position: panoData.location.latLng,
pov: {
heading: 34,
pitch: 10
}
};
var panorama = new google.maps.StreetViewPanorama(document.getElementById('pano'), panoramaOptions);
map.setStreetView(panorama);
}
}
}
});
I can't publish it on jsfiddle as there is a php backend with database, but with the code above and a test point (lat,lng) = (54.226978, 49.568459) you can recreate the problem, you'll see the photo and not the Street View. However, this city and this very point is covered by Street View.
The problem might be that your calling getPanoramaByLocation(). It might work if you omit that, and just do this:
var point = new google.maps.LatLng(54.226978, 49.568459);
window.map.setCenter(point);
window.map.setZoom(14);
var panoramaOptions = {
position: point,
pov: {
heading: 34,
pitch: 10
}
};
var panorama = new google.maps.StreetViewPanorama(document.getElementById('pano'), panoramaOptions);
map.setStreetView(panorama);
Or if you want to getPanoramaByLocation() you should call setPano() in the callback like this:
var point = new google.maps.LatLng(data[0].lat, data[0].lng);
var panorama = new google.maps.StreetViewPanorama(document.getElementById('pano'));
var webService = new google.maps.StreetViewService();
var checkaround = 5000;
webService.getPanoramaByLocation(point,checkaround ,function(panoData) {
if(panoData){
if(panoData.location){
if(panoData.location.latLng){
window.map.setCenter(panoData.location.latLng);
window.map.setZoom(14);
panorama.setPano(panoDdata.location.pano);
panorama.setPov({
heading: 34,
pitch: 10
});
panorama.setVisible(true);
map.setStreetView(panorama);
}
}
}
});
You can try to use Roads API snapToRoads method.
This method takes GPS points collected along a route, and returns with the points snapped to the most likely roads the vehicle was traveling along

Google Map dynamics markers and polylines

The user insert the city of departure and destination in 2 text input, then click on the button to display on the Google Map 2 markers corresponding to the inserted cities and a Polyline between those 2 points.
Here is my code:
//Global array
var pathArray = [];
var cities = [ origin, destination ];
$('#button').on("click", function() {
reverseGeocodeCities(cities);
});
function reverseGeocodeCities(cities) {
$.each(cities, function(index, value) {
geocoder.geocode({'address': value}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
addMarkerCity(results[0].geometry.location);
}
});
});
//Create the polyline just after the loop.
addPolyline();
}
function addMarkerCity(cityPosition) {
var currentMarker = map.addMarker({
position: cityPosition
});
//Add the position of the marker into the global pathArray used by addPolylineCity function.
pathArray.push(currentMarker.getPosition());
}
function addPolylineCity() {
console.log(pathArray); //Display "[]" at the first click.
var polyline = map.drawPolyline({
path: pathArray,
});
I have 2 problems with this code: The first one is, when the user click once on the button, the markers are displayed well on the Google Map but not the polyline between the 2 markers. I have to click twice on the button to make the polyline visible. To create the polyline, I'm using the global array pathArray containing each markers position. It always display an empty array at the first click and then the proper position of the markers after the second click on the button.
The second problem is that I'm doing a simple symbol animation on the created polyline but the flow direction change time to time, if I want to do London to New York, the symbol should slide from London to New york and not the reverse (I removed this part for code simplicity). Please note that I'm using Gmaps wrapper to use Google Map features.
Thanks for your help if you know what I'm doing wrong with my code.
You are creating the polyline first and then the markers, so the polyline does not appear
if (pathArray.length == 2) {
addPolylineCity();
}; //hardcode
An example JSFiddle

how to take snapshot of google map with polyline and openInfoWindowHtml

I'm working on functionality to take snapshot of google map with polylines and open popup window on polyline click on google map.
The snapshot of google map with polylines is working
but it will not able to take snapshot open popup window on polyline.
polyline are showing on sanpshot picture but info window are not showing .
Here is code to take snapshot.
This code is to initialize the code control on javascript onload :
var snapShotControlOptions = { hidden: true };
snapShotControlOptions.buttonLabelHtml="<snap id='snap' style='display:none' >snap</span>"
snapShotControl = new SnapShotControl(snapShotControlOptions);
map.addControl(snapShotControl);
here is the method take snap to take the sanp shot of google map .
function takeSnap() {
//static map size
var sizeStr = "640x640";
var imgSize = "";
if (sizeStr != "") {
var sizeArray = sizeStr.split("x");
imgSize = new GSize(sizeArray[0], sizeArray[1]);
}
snapShotControl.setMapSize(imgSize);
var format = "jpg";
snapShotControl.setFormat(format);
var url = snapShotControl.getImage();
// document.getElementById("snapshot_canvas").src = url;
SaveImage(url);
//
}
//this will add polyline overlay to draw line on google map with different color of polyline on google map .
var polyline = directionsArray[num].getPolyline();
polyline.setStrokeStyle({ color: streetColor, weight: 3, opacity: 0.7 });
polyline.ssColor=streetColor;
map.addOverlay(polyline);
///this code will open the pop info window on polyline those polyline created on google map
and problem is their these pop window not included on sanpshot when i take sanpshot of google map.
var MousePoint = "";
var marker;
GEvent.addListener(map, "mousemove", function (point) {
MousePoint = new GLatLng(point.lat(), point.lng());
});
GEvent.addListener(polyline, "click", function () {
map.openInfoWindowHtml(MousePoint, headMarkerHtml);
});
GEvent.addListener(polyline, "mouseout", function () {
// map.closeInfoWindow();
});
can you please tell who i pass popup window in polyline overlay .
i have use javascript file snapshotcontrol.js to take the snapshot.
from the snapshotcontrol source
This library makes it easy to generate an image "snapshot" of your
interactive map, using the Google Static Maps API.
Static maps doesn't support info windows or anything like adding custom text to the map
https://developers.google.com/maps/documentation/staticmaps/index
You could draw the map on a canvas within the browser then
draw the info window on top of that using this http://html2canvas.hertzen.com/
and then download the canvas content

Categories

Resources