Is it possible to set a "max allowed pitch" for a Mapbox GL map? - mapbox-gl-js

I am unable to find a method to prevent the user from setting the pitch angle of the map too far. I am working with high resolution weather data, so I want to prevent them from setting the pitch so extreme that they can see far away from the intended area. That puts me in a position to either extend the data (WAY too much bandwidth would be used) or just not display it there, making it ugly. I would not like to eliminate the pitch ability completely, as it helps with visualization.
I have looked as much as I can in the documentation but since I cannot find the information and I do not even have a code snippet I have tried because I have nowhere to start. Is there any way to (for example) let the user pitch up to a certain degree only? I made an example image where the left pitch would be OK but not the right, as in that current zoom level it would let them see too far away. If this is not possible, I am open to alternate methods, if any.

Use the render event to check the value of the angle:
map.on('render', (e) => {
if (e.target.getPitch() > MAX_PITCH) e.target.setPitch(MAX_PITCH)
})
[ https://jsfiddle.net/05o4e7dr/ ]

There's now a maxPitch option that you can pass to the Map construct. And, as of Mapbox GL JS 2.0.0, you can set it to pretty high values, all the way up to 85°:
let MAX_PITCH = 85
new mapboxgl
.Map({
container: 'map',
// ...
pitch: MAX_PITCH,
maxPitch: MAX_PITCH,
});

Related

How do you get all features within a bounding box regardless of zoom?

Given a bound box like the below picture, how do you get all the features contained within, regardless of if they are visible or not.
I have tried to get all roads using
let features = map.querySourceFeatures('composite', {sourceLayer: 'road'})
But it only gives me roads that are visible if I am zoomed in.
I have also tried
let features = map.queryRenderedFeatures([tile_info.swPt, tile_info.nePt])
But again, it only gets features visible on the map based on zoom level.
I need all the features within the bounding box regardless of what you can see or zoom level
It is in the nature of vector tiles that you can not do what you want to do here. You can only query data which has been loaded into the browser, and the point of the vector tile architecture is to prevent that happening at lower zooms.
You could consider a server based approach like Tilequery.

How to change map color by current zoom level with mapbox gl js?

My question is about mapbox gl js.
How to change map fill-color by current zoom level?
The fill-color of this map has population growth rates by country, with a gradation from minimum to maximum. However, if the zoomed location has similar data, the fill-color difference becomes difficult to understand. So, I want to refer to the tile information according to the zoom level, get the country on the screen, and redraw it.
I searched a lot, but I couldn't figure out how to get the information on the screen. Please let me know if you have any information.
Zoom Level: 1
Zoom Level: 3
Thank you!
Your question initially asks:
How to change map color by current zoom level with mapbox gl js?
For that, you use an expression like 'fill-color': ['interpolate', ['linear'], ['zoom'], ...]
But what you want is something very different:
However, if the zoomed location has similar data, the fill-color difference becomes difficult to understand. So, I want to refer to the tile information according to the zoom level, get the country on the screen, and redraw it.
It sounds like what you want is context-sensitive color scaling. That is, instead of a fixed scale of colors where dark green always means X and light green means Y, instead, dark is the lowest value in the current viewport and light is the highest value in the viewport.
This does not have anything to do with zoom.
The steps you need are:
Detect when the viewport has changed: map.on("moveend", ...)
Find what values exist within the viewport: map.queryRenderedFeatures(...)
Calculate a new expression based on those values.
Set the new expression: map.setPaintProperty(...)

Equivalent of map.cameraForBounds without a Mapbox GL Map instance

With Mapbox GL JS, I can get a center and zoom level to show all of a given bounding box using the cameraForBounds method:
const {center, zoom} = map.cameraForBounds(
[
[sw.lng, sw.lat],
[ne.lng, ne.lat],
],
{
padding: 20,
bearing,
pitch, // probably ignored?
},
);
(The typings say that pitch is OK but the docs don't mention it and neither does the implementation, so I assume it's ignored.)
This usually works great, but there occasionally situations where I want to figure out the center/zoom before the map is initialized. It seems like the bounds → camera transformation should just be math, not requiring a Map instance.
How can I go from bounds and bearing (and ideally pitch) to a center/zoom that will include those bounds without an instance of a Mapbox GL map?
You can't, for the simple reason that you don't know how many pixels this map will occupy. Setting a centre and zoom determines how much area (and which area) will be covered by each pixel in the middle of the map. The bigger the map DOM element is, the more area will be covered by the area within the map.

Is it possible to exclude pins at zoom levels

Created my first map at
http://rich.littlebigfoot.org.uk/test7.html
I am plotting walks on the coast path (the yellow) and will be adding more walks and more information. However at current zoom I would like to exclude all the pins and only show them at zoom level 11?
Thanks
Rich
If I understand correctly, you want to hide some layers (pins/markers and/or vectors/paths) at some low zoom levels (like [0 to 10]), and bring them back at high zoom levels (like 11 and above)?
You would probably be interested in attaching a callback on map "zoomend" event, so that callback can remove or add your layers to the map depending on the current map zoom level, when the latter changes.
For example:
map.on("zoomend", showOrHideLayers);
function showOrHideLayers() {
if (map.getZoom() <= 10) {
map.removeLayer(markers);
} else {
map.addLayer(markers);
}
}
showOrHideLayers();
Demo: http://jsfiddle.net/ve2huzxw/116/
EDIT:
If your objective is to avoid overlapping of pins (markers), you might also be interested in "Clustering" functionality.
Have a look at available Leaflet clustering plugins.
The most popular one is Leaflet.markercluster (demo).

Zoom causes (heavy) problems in Bing Maps with polylines

Hello i have some problems with the Bing Map control.
If i zoom to near to the polylines they begin to disappear (from bottom to top and from right to left)
The Polylines are generated dynamically with an ItemsControl (that one which is included in the maps namespace) bound to a collection of my own LocationData from ViewModel thats converted by a IValueConverter to the map specific LocationPoints.
Some values that are not accessible from ViewModel are set in the loaded event.
The map and the container stretch over the whole screen.
So if the lines begin to disappear and i zoom out via a button in my ApplicationBar
private void ZoomOut_Click(object sender, RoutedEventArgs e)
{
map1.ZoomLevel -= 1.0;
}
the Application exits without exception...
I have tested it on a real device with and without debugger and the debugger only says that he have lost the connection to the device.
Anyone have this or similar problems and hopefully solved it?
Thanks for any help.
PS: My LocationData contains approximately 100 - 200 points that are split up to 3 - 7 lines that can't be to much or?
Yes, hundreds of points is too much, but that's the least of your problems. The way you have coded this, you are reconverting and replotting your points every time there is a pan or zoom.
Don't use the type converter. Convert your points once, cache the converted points and bind to the converted points.
Research quadtrees and how they apply to culling your point set in proportion to zoom level.
Apply a clipping rectangle. In my experience, half a degree larger each side of your display region works well.
Study the Bing map event model and redesign your code so that you only cull, clip and plot when map manipulation stops.
Ideally, write your cull, clip and plot logic so that it is asynch and can be signalled to abort so that if manipulation restarts before cull, clip and plot is finished, it can be aborted and restarted.
Using the techniques above I am able to get performance comparable to the built-in map.