Leaflet - custom tile layer - get lat long coordinates - leaflet

My requirement is be able to call an api which returns me GeoJson - this api requires the bounding box in lat/long coordinates. I would like to be able to have this api called for each tile but am stuck trying to convert the L.Coords x,y,z values to bounds.
I would have thought this would be a common use case - is there another way I should be approaching this problem?
Code demonstrates my approach.
L.TileLayer.Custom = L.TileLayer.extend({
getTileUrl: (coords: L.Coords) => {
const bounds = coords?.getBounds();
const geometry = {
ymin: bounds?.getSouth(),
xmin: bounds?.getWest(),
ymax: bounds?.getNorth(),
xmax: bounds?.getEast()
};
// call api Api.call(geometry).then(...)
},
});
L.tileLayer.custom = function () {
return new L.TileLayer.Custom();
};
L.tileLayer.custom().addTo(map);

Related

How to get polyline coordinates React-Leaft-Draw plugin?

I use this plugin to draw lines on Leaflet map in my project:
https://github.com/alex3165/react-leaflet-draw
I want to get coordinates (lat,long) of drawn polyline, when _onCreate or later. How could i do this?
I agree, the documentation is a bit lacking, so I hope this helps anyone else trying to do this. You first implement an onCreated function that is registered on the <EditControl> component. You can then access the current layer object and its layerType from the event object that gets passed to this callback.
Depending on the shape type, you can access the coordinates of the shape via a the methods provided by Leaflet (e.g. circle). See code below.
export default DrawTool({prop1, prop2) {
const onCreated = (e) => {
if (e.layerType === 'circle') {
console.log("circle center, radius =", e.layer.getLatLng(), e.layer.getRadius())
} else {
// polygon & rectangle
console.log("polygon coordinates =", e.layer.getLatLngs()) // array of LatLng objects
} // marker or lines, etc.
// map.addLayer(e.layer) // might need?
}
const onDelete = (e) => {
// do something with e.layer
}
return (
<EditControl
position='topright'
onCreated={onCreated}
onDeleted={onDeleted}
...
/>
)
}

Leaflet Bounds Not Updated

I have a problem with a function allowing to change the position of a marker on my leaflet map.
I update the coordinates of my map with a zoom to 17.
However when I call my recupObjectByLatLong function by passing mapRef.current.getBounds (), the map has not yet updated the bounds in relation to the zoom of the new coordinates.
To prevent the problem today, I put a setTimeout, however I don't think this is the cleanest solution ...
function changePositionMarker(e) {
const latitude = e.latlng.lat;
const longitude = e.latlng.lng;
mapRef.current.setView(L.latLng(latitude, longitude), 17);
markerRef.current.setLatLng([latitude, longitude]);
markerRef.current.bindPopup('test').openPopup();
setTimeout(() => {
recupObjectByLatLong(mapRef.current.getBounds().getNorthEast().lat, mapRef.current.getBounds().getNorthEast().lng, mapRef.current.getBounds().getSouthWest().lat, mapRef.current.getBounds().getSouthWest().lng);
}, 1000);
}

How to change the color of results from leaflet-knn on the map

I have displayed the the result markers for the leaflet-knn on the map with following code:
const myloc = new L.LatLng(13.7433242, 100.5421583);
var gjLayer = L.geoJson(testCities, {
onEachFeature: function(feature, layer) {
content = "<b>Name:</b> " + feature.properties.name;
layer.bindPopup(content);
}
});
var longitude = myloc.lng,
latitude = myloc.lat;
var res = leafletKnn(gjLayer).nearest(
[longitude, latitude], 5, distance);
for (i = 0; i < res.length; i++) {
map.addLayer(res[i].layer);
}
Now I want to change the color of this marker that is added or I want to change the icon.
Can anybody tell me how can I do?
Leaflet-knn is agnostic when it comes to the representation of the results - it relies on the existing L.Layers: it takes a L.GeoJSON as an input and then iterates through all its members in order to fetch all their coordinates (in the case of polylines and polygons) and then store a reference to the L.Layer for each of its coordinates.
The results of a leaflet-knn search include the original L.Layer from the L.GeoJSON that was passed at instantiation time.
Either symbolize your GeoJSON afterwards, as explained in the Leaflet tutorials, or create new markers/symbols for the results after each query.
Right now your code is relying on the default symbolization of GeoJSON data (instantiate a L.Marker with a L.Icon.Default for points). I suggest the approach of displaying your L.GeoJSON in the map to ensure that it looks like you want it to (even if it's a partial set of the data), then implementing the leaflet-knn search.

Mapbox GL JS: zoom to filtered polygon?

I am using Mapbox GL JS to display a polygon layer. I would to allow the user to choose a name from a dropdown, and then highlight and zoom to the matching polygon.
I already know how to highlight the matching polygon using map.setFilter, but I don't know how to zoom to the bounds of the matching polygon. This is my current code:
map.addLayer({
'id': 'polygon_hover',
'source': 'mysource',
'source-layer': 'mylayer',
'type': 'fill',
'paint': {
'fill-color': 'red',
"fill-opacity": 0.6
},
"filter": ["==", 'CUSTNAME', ""]
});
// Get details from dropdown
custname.on("change", function(e) {
// get details of name from select event
map.setFilter('polygon_hover', ["==", 'CUSTNAME', name]);
// Get bounds of filtered polygon somehow?
// var bounds = ??;
// map.fitBounds(bounds);
});
I have examined the Mapbox example of zooming to bounds, but it assumes that you already know what the bounds are.
Is there any way it's possible to get the bounds of the polygon matching a map filter in Mapbox?
I've the following code to fitBounds to Polygon center coords:
var coordinates = f.geometry.coordinates[0];
var bounds = coordinates.reduce(function (bounds, coord) {
return bounds.extend(coord);
}, new mapboxgl.LngLatBounds(coordinates[0], coordinates[0]));
map.fitBounds(bounds, {
padding: 20
});
Where f is one Feature.
I found a solution to your problem. Leaflet has a polygon Class which takes an Array of polygon coordinates and has a function called getBounds() that returns south west and north east bounds. However, Leaflet doesn't follow the convention of LngLat, its format is LatLng. Therefore, you have to switch it. I took an example out from Mapbox Show drawn polygon area, and added exactly what you're looking for.
var polygon = data.features[0].geometry.coordinates;
var fit = new L.Polygon(polygon).getBounds();
var southWest = new mapboxgl.LngLat(fit['_southWest']['lat'], fit['_southWest']['lng']);
var northEast = new mapboxgl.LngLat(fit['_northEast']['lat'], fit['_northEast']['lng']);
var center = new mapboxgl.LngLatBounds(southWest, northEast).getCenter();
// map.flyTo({center: center, zoom: 10});
map.fitBounds(new mapboxgl.LngLatBounds(southWest, northEast));
I see that the question is still relevant - I solved it making a separate request to the database containing all points of a given polygon and building bounds [[minLng, minLat], [maxLng, maxLat]].
All attempts to address geometry of already rendered or source features didn't work for me - most probably because Mapbox doesn't keep initial geoJSON in the tiles.

Start-Marker from geojson polyline

i have a map with some walking- and bike-routes and popups with a few details an a pic. Now i want to set a marker on the first vertex of a geojson polyline, but i cant find out how. Btw. i´m new to leaflet/mapbox, and i put my map togehter from code snippets.
Here is the map now:
This is how i create the polylines now. I call them via layercontrol.
var mtb = L.geoJson(radjs, {
filter: function (feature, layer) {
if (feature.properties) {
// If the property "underConstruction" exists and is true, return false (don't render features under construction)
return feature.properties.typ === 'mtb';
}
return true;
},
style: {
"color": '#6699cc',
dashArray: '',
"weight": 4,
"opacity": 0.6
}, onEachFeature: onEachFeature2}).addTo(rad);
Thank you for your help,
Marc
You could just add a Feature to your geojson with the latitude and longitude like the do it in the Leaflet GeoJSON Example.
Probably it will be more convenient to read the geometry.coordinates from geojson features and define a new marker.
Beside you have an error on line 569. You should change:
var map = L.mapbox.map('map','',{
to:
var map = L.mapbox.map('map',null,{
Create a simple marker object and add it to the map.
marker = L.marker([0, 0], {
icon: L.mapbox.marker.icon()
}).addTo(map)
Then set the latitude and longitude to the first coordinates of your geoJSON. Assuming your geoJSON is set to the var geojson, you can access the coordinates by indexing into the array.
marker.setLatLng(L.latLng(
geojson.coordinates[0][1],
geojson.coordinates[0][0]))