Leaflet panTo (or setview) function? - javascript

I want to create a panTo -function. When I click a link the map pans to the coordinates. But im not sure how to pass the value to the function. I'm starting with giving the link the Pointfield (pt) value like this:
Link
Then I've been trying this:
$("#dialog").on("click", ".marker", function(e) {
e.preventDefault();
map.panTo($(this).attr("value"));
});
That didn't work. I think it's a scope-issue where the function cant read the 'map' variable because it's not under the initial map script.
So my next idea is to create a "panTo"- function and place it under the inital map script (which would be the right scope) and call that function from the click event instead. Not sure it would work but Im wondering how to pass it the "value" from the link?
Thanks for your answers!

You can add navigation to your map by utilizing data attributes in your HTML. Save the latitude,longitude and zoom to something like data-position and then call those values with some JavaScript when the user clicks on the anchor tag. Here's some code to illustrate.
<div id="map">
<div id="map-navigation" class="map-navigation">
<a href="#" data-zoom="12" data-position="37.7733,-122.4367">
San Francisco
</a>
</div>
</div>
<script>
var map = L.map('map').setView([51.505, -0.09], 13);
L.tileLayer('http://{s}.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/997/256/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © CloudMade'
}).addTo(map);
document.getElementById('map-navigation').onclick = function(e) {
var pos = e.target.getAttribute('data-position');
var zoom = e.target.getAttribute('data-zoom');
if (pos && zoom) {
var loc = pos.split(',');
var z = parseInt(zoom);
map.setView(loc, z, {animation: true});
return false;
}
}
</script>

Related

leaflet geoman - load pre-existing polygon to map

I have the following jsfiddle and wonder how can I click the dummy button add the predefine polygon coordinates?
[[[7.43067, 49.109838], [7.43067, 50.331436], [10.135936, 50.331436], [10.135936, 49.109838]]]
My javasript:
var osmUrl = 'http://{s}.tile.osm.org/{z}/{x}/{y}.png',
osmAttrib = '© OpenStreetMap contributors',
osm = L.tileLayer(osmUrl, {
maxZoom: 18,
attribution: osmAttrib
});
// initialize the map on the "map" div with a given center and zoom
var map = L.map('map').setView([50, 8], 6).addLayer(osm);
// add leaflet.pm controls to the map
map.pm.addControls();
map.on('pm:create', ({
workingLayer
}) => {
self_drawn = map.pm.getGeomanDrawLayers(true)
console.log(self_drawn.toGeoJSON())
});
function loadSquare()
{
console.log("ok load the square");
}
My html
<div id="map"></div>
<button ion-button class="button-action" onclick="loadSquare()" block>Load Square!</button>
Before:
After click the Load Square button, get a gemoan with:
Use the default L.GeoJSON object from Leaflet.
function loadSquare(){
console.log("ok load the square");
L.geoJSON(data).addTo(map); // data = console.log(self_drawn.toGeoJSON())
}

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.

How to get the desired value for lat,long to display only the required portion of the map with Leaflet.js?

I am trying to display a portion of a map with this amount of code:-
<div id="mapid" style="height: 280px; width: 1143px;">
<script src="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.js"></script>
<script>
var mymap = L.map("mapid").setView([5, 120], 13);
L.tileLayer("http://{s}.tile.osm.org/{z}/{x}/{y}.png", {
attribution: '© OpenStreetMap contributors',
}).addTo(mymap);
</script>
</div>
But that displays this portion of the map:-
But I am trying to get this portion of the map:-
is there any tool I can optimize my code to do so:-
You can set the view of the map with: map.setView([lat,lng],zoom)
For your example: mymap.setView([-3.687845, 113.776067], 4);
Or you can set the bounds (top left corner and right bottom corner) of the map, so the map is calculated what is the best zoom to contain the bounds.
var bounds = L.latLngBounds([6.884470, 94.897447],[-13.549102, 154.879214])
mymap.fitBounds(bounds)
But to answer your question, you can get the latlng when you click on the map with:
map.on('click',function(e){
console.log(e.latlng);
});

Leaflet map reload onclick

I have a gallery of image thumbnails and a image viewer. Each image has different #id has lat and long attached to it. I am triggering series of onclick events on clicking the thumbnail. The imagename, lat and long info is stored in a mysql table. The following are the functions I have written sofar.
function clickedImage(clicked_id) {
//series of functions
$.post("getLatLong.php",{"clickedimag":clickedImg},function(data){
var ll = JSON.parse(data);
var lat = parseFloat(ll[0]);
var long = parseFloat(ll[1]);
var pname = ll[2];
localStorage.setItem('lat',lat);
localStorage.setItem('long',long);
localStorage.setItem('cpname',pname);
//alert([lat,long]);
});
//Series of functions
}
All my other functions are working including I am able to save lat, long info into localStorage. The alert in the above function, clearly pops up with the lat and long attached to the image. To render the map, I am using the template given in the leaflet page.
$(function(){
var la = localStorage.getItem('lat');
var lon = localStorage.getItem('long');
var cpname = localStorage.getItem('cpname');
var mymap = L.map('mapid').setView([la,lon], 13);
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Ima$
maxZoom: 18,
id: 'mapbox/streets-v11',
tileSize: 512,
zoomOffset: -1,
accessToken: 'my.access.token'
}).addTo(mymap);
var marker = L.marker([la, lon]).addTo(mymap);
marker.bindPopup("<b>" + cpname +"</b>").openPopup();
});
The above code works and renders the map correctly, however, only when I refresh the page. It is not changing the map asynchronously. I have tried this function too:
function getMyMap(la,lon) {
var la = localStorage.getItem('lat');
var lon = localStorage.getItem('long');
var mymap = L.map('mapid').setView([la,lon], 13);
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Ima$
maxZoom: 18,
id: 'mapbox/streets-v11',
tileSize: 512,
zoomOffset: -1,
accessToken: 'myaccesstoken'
}).addTo(mymap);
}
and called this function inside my onClick event. I am getting the same result.
HTML
<div class="rhsbar" id="rhsbar" style="overflow:hidden;display:flex;flex-direction:column;">
<div id="mapid" >Loading map</div>
</div>
var h = $("#rhsbar").height();
var w = $("#rhsbar").width()+100;
document.getElementById("mapid").style.height=h+"px";
document.getElementById("mapid").style.width=w+"px";
How do I update the map with new coordinates without refreshing the page.
What you need is:
your_mapid.fitBounds(your_mapid.getBounds());
It will do a soft refresh of the map whenever something changes.

Leaflet - Center map on marker, zoom and open popup

I have leaflet map that draws markers from geojson and binds popups to them. GeoJSON feature collection is stored in geojsonFeature variable. The code looks like this:
<script>
var map = L.map('map').setView([42.652, 18.102], 13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
var sidebar = L.control.sidebar('sidebar').addTo(map);
function onEachFeature(feature, layer) {
var popupContent = '<h3>'+feature.properties.Naziv+'</h>';
if (feature.properties.Slika) {
popupContent += '<br /><img src="slike/'+feature.properties.Slika+'.jpg" alt="Slika" style="width:300px;">';
}
layer.bindPopup(popupContent);
}
L.geoJSON(geojsonFeature, {
onEachFeature: onEachFeature
}).addTo(map);
</script>
This works fine, but I want to add a list with features outside the map. The list would be clickable and an onClick event would pass feature id to the function that zooms the map on selected feature and opens the popup.
The only problem is that I don't know how to zoom map to the feature and open the popup programmatically using the point's ID from source GeoJSON.
Found a way to work around this. I added a clickable list of features outside of map with ID-s and "ref" class. Then I made the following jQuery listener:
$(".ref").click(function () {
//extract ID from list HTML element
var id=eval(this.id);
//find object with extracted ID in original GeoJSON
//use object's coordinates and features to pan the map and display popup
map.setView([geojsonFeature.features[id].geometry.coordinates[1], geojsonFeature.features[id].geometry.coordinates[0]], 16);
var popupData = '<h3>'+geojsonFeature.features[id].properties.Naziv+'</h>';;
if(geojsonFeature.features[id].properties.Slika) {
popupData += '<br /><img src="slike/'+geojsonFeature.features[id].properties.Slika+'.jpg" alt="Slika" style="width:300px;">';
}
var popup = L.popup()
.setLatLng([geojsonFeature.features[id].geometry.coordinates[1], geojsonFeature.features[id].geometry.coordinates[0]])
.setContent(popupData)
.openOn(map);
});

Categories

Resources