MapBox - Uber-like location picker - mapbox

I'm trying to make an Uber-like location picker with MapBox. I would like to 'freeze' map on fixed marker (that's in center of the map) when zooming.
By default, whenever you zoom, map is actually zooming to the click/pinch point where you started the zoom rather than to map center. I almost got it but now I'm battling the centering transition (I don't want it).
Is there any trick to achieve that? Currently I'm trying to work with mapbox events zoomend and move. Unfortunately zoom throws too many events and the map is lagging like hell:
let markerLocation = map.getCenter();
const marker = new mapboxgl.Marker()
.setLngLat(markerLocation)
.addTo(map);
map.on(`zoomend`, (e) => {
map.flyTo({
center: markerLocation,
});
});
map.on(`move`, (e) => {
if (map.isZooming()) {
return;
}
markerLocation = map.getCenter();
marker.setLngLat(markerLocation);
});
Please find the JsFiddle: https://jsfiddle.net/pawelol/kpu8nzh9/2/
Any help will be highly appreciated :)

Related

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);
}

Leaflet zoom control don't zoom in or out

I have an animation, which starts like this:
Window.map = new L.Map('map', {
zoomControl: false
});
L.control.zoom({position:'topleft'
}).addTo(Window.map);
//add tile layers
var basemapLayer = new
L.TileLayer('https://{s}.tiles.mapbox.com/v4/github.map-xgq2svrz/{z}/{x}/{y}.png?ac$
token: '.....'
});
And then I am adding feature layers set zoom min and max, and it did not work either. I may hide it, change the position, but when I click on the '+' or the '-' nothing happens.
I am using the default css from leaflet.

Mapbox GL JS: Control max zoom with geolocation control?

I am using Mapbox GL JS v0.32.1 and I have a geolocation control on my map.
I would like to make it so that the maximum zoom when the user geolocates is 8, so that the map zooms to the user's approximate location, not street location.
According to the documentation there should be a geolocate event available, but this isn't working for me:
var geoLocate = map.addControl(new mapboxgl.GeolocateControl());
geoLocate.on('geolocate', function(e) {
console.log('geolocated');
map.setZoom(8);
})
Geolocating (in Chrome at least) still zooms to the maximum zoom level available, and I don't see a console log message when it happens.
Map#addControl returns Map. The geolocate event is fired on GeolocateControl. The following should work:
var geoLocate = new mapboxgl.GeolocateControl();
map.addControl(geoLocate);
geoLocate.on('geolocate', function(e) {
console.log('geolocated');
map.setZoom(8);
});
Try this way. smooth zoom to your location
var geoLocate = new mapboxgl.GeolocateControl();
map.addControl(geoLocate);
geoLocate.on('geolocate', function(e) {
map.flyTo({
center:[e.coords.longitude, e.coords.latitude],
zoom:16 //set zoom
});
});

Getting the bounds of loaded tile of leaflet

Using leaflet is there any way I can get the bounds (NorthEast, SouthWest) of a loaded tile? I want to request the server to load the markers only for a particular tile which is loaded, so that when user is panning/dragging the map he can easily see the new markers on new area.
What you really want to do is a subclass of L.GridLayer. This will allow fine control over loaded/unloaded tiles, and is the best way to use the private L.GridLayer._tileCoordsToBounds() method.
With some basic handling of loaded markers, it should look like:
L.GridLayer.MarkerLoader = L.GridLayer.extend({
onAdd: function(map){
// Add a LayerGroup to the map, to hold the markers
this._markerGroup = L.layerGroup().addTo(map);
L.GridLayer.prototype.onAdd.call(this, map);
// Create a tilekey index of markers
this._markerIndex = {};
},
onRemove: function(map){
this._markergroup.removeFrom(map);
L.GridLayer.prototype.onRemove.call(this, map);
};
createTile: function(coords, done) {
var tileBounds = this._tileCoordsToBounds(coords);
var tileKey = this._tileCoordsToKey(coords);
var url = ...; // Compute right url using tileBounds & coords.z
fetch(url).then(function(res){
if (!key in this._markerIndex) { this._markerIndex[key] = []; }
// unpack marker data from result, instantiate markers
// Loop as appropiate
this._markerGroup.addLayer(marker);
this._markerIndex[key] = marker;
done(); // Signal that the tile has been loaded successfully
});
},
_removeTile: function (key) {
for (var i in this._markerIndex[key]) {
this._markerGroup.remove(this._markerIndex[key][i]);
}
L.GridLayer.prototype._removeTile.call(this, key);
}
});
Please note that zooming might be a source of bugs and graphical glitches (markers being removed because a tile unloads, before the markers at the new zoom level are loaded). Beware of that.

Mapbox GL directions plugin hiding search origin destination box

I am using Mapbox GL directions plugin inside my app where I set the origin on map load and set driving destination upon user click on any location on the map. I am now trying to remove the top left search origin / destination box yet after extensive research can't figure out how to do so, can someone please help by telling me how to do so? Thanks.
Code I am using in my app below:
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v8',
center: [userCoordinates.coords.longitude, userCoordinates.coords.latitude],
zoom: 15
});
var directions = new mapboxgl.Directions({
unit: 'metric',
profile: 'driving'
});
map.addControl(directions);
directions.setOrigin([userCoordinates.coords.longitude, userCoordinates.coords.latitude]);
map.on('click', function(e) {
var features = map.queryRenderedFeatures(e.point, { layers: ['gsLayer'] });
if (!features.length) {
return;
}
var feature = features[0];
directions.setDestination([feature.geometry.coordinates[0], feature.geometry.coordinates[1]]);
});
I couldn’t figure this out either since there is no documentation, but finally I read through the mapbox-gl-directions.js file and I think I found out how to do it.
In your example, you should embed the controls like this in order to remove the origin / destination box:
var directions = new mapboxgl.Directions({
unit: 'metric',
profile:'driving',
container:'directions', // Specify an element thats not the map container.
// UI controls
controls: {
inputs: false,
instructions: true
}
});
map.addControl(directions);
I'll assume you are using Mapbox GL Javascript, and looking at this example it appears map.addControl(new mapboxgl.Directions()); is what is adding the controller. Within your code you gave you also have this map.addControl(directions);. Try removing it and see what happens.
Hope this helps!