I want to be able to hide and show/layers in Mapbox like this example provided by Mapbox.... https://docs.mapbox.com/mapbox-gl-js/example/toggle-layers/
I have some vector data saved as a tile set in Mapbox, but I don't know where to find the URL is shown in the example below as 'mapbox://mapbox.2opop9hr'. Can anyone tell me how to find it for my own data?
// Wait until the map has finished loading.
map.on('load', () => {
// Add a custom vector tileset source. This tileset contains
// point features representing museums. Each feature contains
// three properties. For example:
// {
// alt_name: "Museo Arqueologico",
// name: "Museo Inka",
// tourism: "museum"
// }
map.addSource('museums', {
type: 'vector',
url: 'mapbox://mapbox.2opop9hr'
});
mapbox://mapbox.2opop9hr is a reference to a mapbox custom vector tileset. You can make one of your own by uploading data in Mapbox Studio: https://docs.mapbox.com/studio-manual/reference/tilesets/. Mapbox will then serve this tileset for your map to consume.
However, this isn't necessary to toggle map layers using the technique shown in the example. map.setLayoutProperty() can be used to show or hide any layer, including layers that came with the base style, or layers added after the fact using vector tiles or geojson sources.
If you are working with small/simple data, you may want to just add a geojson source and layer, and then use setLayoutProperty() to show and hide it as in the example.
Related
I have a network of roads displaying on a layer in Mapbox. On mouseenter of a given individual road segment, I want to change it's line-color. I'm able to successfully change all the roads together as a whole, but how can I target a single road segment and change its color?
I've tried things like this but haven't found much luck targeting an invidual road segment:
map.on('mouseenter', 'road-street', (e) => {
map.getCanvas().style.cursor = 'pointer';
let uniqueId = "road-" + String(Date.now());
e.features[0].layer.id = uniqueId;
map.setPaintProperty(e.features[0].layer.id, 'line-color', '#0099ff');
});
But this generates an Object Error
Layers like road-street in Mapbox Streets don't contain unique attributes (such as an ID) that would let you easily color them individually. However, they do have unique geometry (with some caveats: the geometry of an individual feature is not necessarily the whole road, or what you expect to find as "the road").
You can do something like this:
Create a separate source selected-road of type line
Create a separate layer selected-road of type line, connected to the source.
When the user clicks/hovers, update its geometry like this:
map.getSource('selected-road').setData(e.features[0].geometry)
I am trying to use the leaflet-draw tool for two different things:
as a "regular" tool to create new geometries
if I draw a line, I perform some calculations with turf.js, giving me points nearby.
I've set up two individual draw controls for each purpose. For the second, I have all but the draw:polyline disabled. The problem: I save my elements with the
map.on('draw:created', function(){...});
"command". But this way I (or the eventhandler, respectively :)) cant differentiate, if the line was drawn with the first or the second button. So basically i can use the draw tool either for one thing or the other. Is there a way where I can use the same tool for different applications on the same map?
Thanks for any hints or work arounds.
An alternative would be to use Leaflet-Geoman instead of Leaflet-Draw.
There you can create copies of Draw instances and add them a new shape name:
// copy a rectangle and customize its name, block, title and actions
map.pm.Toolbar.copyDrawControl('Polygon', {
name: 'PolygonCopy',
block: 'custom',
title: 'Display text on hover button',
actions: ['cancel', 'removeLastVertex', 'finish'],
});
And then you can check the shape name in the create event:
// listen to when a new layer is created
map.on('pm:create', function(e) {
console.log(e)
if(e.shape === 'Polygon'){
alert('Original Polygon')
}else if(e.shape === 'PolygonCopy'){
alert('Copy Polygon')
}
});
https://jsfiddle.net/falkedesign/r0sm9auo/
When creating a polygon using Mapbox GL Draw I do not want the polygon to then be editable, clickable etc. After ending the draw event, I'd like to to just appear as finished like below when it's deselected.
Maybe this is embedded in the simple_select config option?
The Mapbox Draw plugin provides an interface for writing and hooking in custom modes, where a mode is defined as way to group sets of user interactions into one behavior. Mapbox Draw Static Mode is a custom mode that displays data stored in Draw but does not let users interact with it, which sounds like what you are looking for.
modes.simple_select.onDrag function disable the onDrag event.
I give you a small example to can contextualize it.
Inside your #map-init method you should have:
const modes = MapboxDraw.modes;
let draw = new MapboxDraw({
// your mapBoxDraw options
});
map.on("draw.create", updateArea);
modes.draw_polygon.clickAnywhere = function (state, e) {
//your polygon click restrictions
}
modes.simple_select.onDrag = function (state, e) {
//when polygon is deselected onDrag will be false and user not be able to drag it
};
function updateArea(e) {
// your stuff when you're drawing
}
I'm new to mapbox studio and trying to access data in the properties of my uploaded geojson.
Data is successfully added to my style as two layers. Layer one is for the red dots as added as circles and layer two is for the labels as symbols.
As seen here this works fine for values which are directly in the properties object:
Unfortunately it is not possible to display data which is in an object inside the properties object:
My question is, how can I access these values?
I have a application that shows a highlighted list of countries on a map and their names in a side panel
I would like to make the following happen: When you click on the name of a country in the side panel. you zoom to the country on the map.
I am not sure how to make this happen and would appreciate it if someone point me to an example or suggest the best way to make this happen
Really depends upon your set-up and I'am assuming you are using geoJSON. In a project I worked on, I created a function that is ran once you click from a list that zooms to the corresponding geoJSON ... or you could attach the leaflet ID for each geoJSON layer to the corresponding elements of the list if the list populated from the geoJSON.
markers - collected geoJSON
layer.feature.properties.pin - the corresponding key that matches the listed record with the geoJSON (this needs to match your data)
pin - the corresponding element from the list (this needs to match your data)
The 1st setStyle - highlights the geoJSON
map.fitbounds - zooms to highlighted info
The 2nd setStyle - changes all of the other geoJSON layers back to the original style.
function selectedparcel(pin){
markers.eachLayer(function (layer){
if (layer.feature.properties.pin === pin){
layer.setStyle({
fillColor: '#2262CC',
fillOpacity: 1,
weight: 3
});
//this is where the zoom happens
map.fitBounds(layer.getBounds());
} else {
layer.setStyle({
color: '#ff7800',
weight: 1,
opacity: 1,
fillOpacity: 0
});
}
});
I hope this is what you were looking for. If you want to use the leaflet id method Bryan McBride has an example within his js code here:
https://github.com/bmcbride/building-damage-reporter