Show and hide layer properties in Mapbox GL JS

I found the following code to show and hide layers in Mapbox GL:

https://www.mapbox.com/mapbox-gl-js/example/toggle-layers/

This is useful, however, I only have one .geojson (polyline) layer with all the necessary data and I do not need to create separate layers.

I would like to make the same function to show and hide the functions of one layer in the map menu. There are a total of 12 different types of objects that are contained in the Type column. I would like to turn types on and off, as in the example.

Is there an easy way to do this in JS using set.Filter ? https://github.com/mapbox/mapbox-gl-js/blob/e9386d2880cc2c33e9a5a16b9bcb58834026a078/js/ui/map.js#L559-L562

I could not find a solution.

My .geojson layer is here: https://iskandarblue.imtqy.com/mapbox/data/simplify_prototype.geojson

 <!DOCTYPE html> <html> <head> <meta charset='utf-8' /> <title></title> <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' /> <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.15.0/mapbox-gl.js'></script> <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.15.0/mapbox-gl.css' rel='stylesheet' /> <style> body { margin:0; padding:0; } #map { position:absolute; top:0; bottom:0; width:100%; } </style> </head> <body> <style> #menu { background: #fff; position: absolute; z-index: 1; top: 10px; right: 10px; border-radius: 3px; width: 120px; border: 1px solid rgba(0,0,0,0.4); font-family: 'Open Sans', sans-serif; } #menu a { font-size: 13px; color: #404040; display: block; margin: 0; padding: 0; padding: 10px; text-decoration: none; border-bottom: 1px solid rgba(0,0,0,0.25); text-align: center; } #menu a:last-child { border: none; } #menu a:hover { background-color: #f8f8f8; color: #404040; } #menu a.active { background-color: #3887be; color: #ffffff; } #menu a.active:hover { background: #3074a4; } </style> <nav id="menu"></nav> <div id="map"></div> <script> mapboxgl.accessToken = 'pk.eyJ1IjoiaXNrYW5kYXJibHVlIiwiYSI6ImNpazE3MTJldjAzYzZ1Nm0wdXZnMGU2MGMifQ.i3E1_b9QXJS8xXuPy3OTcg'; var map = new mapboxgl.Map({ container: 'map', style: 'mapbox://styles/mapbox/streets-v8', zoom: 15, center: [-71.97722138410576, -13.517379300798098] }); map.on('style.load', function () { map.addSource('museums', { type: 'vector', url: 'mapbox://mapbox.2opop9hr' }); map.addLayer({ 'id': 'museums', 'type': 'circle', 'source': 'museums', 'paint': { 'circle-radius': 8, 'circle-color': 'rgba(55,148,179,1)' }, 'source-layer': 'museum-cusco' }); map.addSource('contours', { type: 'vector', url: 'mapbox://mapbox.mapbox-terrain-v2' }); map.addLayer({ 'id': 'contours', 'type': 'line', 'source': 'contours', 'source-layer': 'contour', 'layout': { 'line-join': 'round', 'line-cap': 'round' }, 'paint': { 'line-color': '#877b59', 'line-width': 1 } }); }); addLayer('Contours', 'contours'); addLayer('Museums', 'museums'); function addLayer(name, id) { var link = document.createElement('a'); link.href = '#'; link.className = 'active'; link.textContent = name; link.onclick = function (e) { e.preventDefault(); e.stopPropagation(); var visibility = map.getLayoutProperty(id, 'visibility'); if (visibility === 'visible') { map.setLayoutProperty(id, 'visibility', 'none'); this.className = ''; } else { this.className = 'active'; map.setLayoutProperty(id, 'visibility', 'visible'); } }; var layers = document.getElementById('menu'); layers.appendChild(link); } </script> </body> </html> 
+5
source share
1 answer

I tried to do the same and ended up using combo filters. Like you, I have a map with a geoJSON source:

 map.addSource( 'routes', { 'type': 'geojson', 'data': geoJSON }); 

On this map, I have a layer with all my routes:

 map.addLayer({ 'id': 'route-no-hover', 'type': 'line', 'source': 'routes', 'layout': { 'line-join': 'round', 'line-cap': 'round' }, 'paint': { 'line-color': '#333', 'line-opacity': 0.25, 'line-width': 4 } }); 

I list all my routes and give the user accessibility to turn it on and off. It seems my concept of β€œroutes” is equivalent to your β€œtypes”. When a user clicks a route name to disable it, I push this route identifier into an array called "hidden" and then create a series of filters based on these identifiers:

  let hiddenFilters = ['all']; _.forEach( mapMeta.hidden, ( route ) => { hiddenFilters.push([ '!=', 'id', route.toString() ]); }); map.setFilter( 'route-no-hover', hiddenFilters ); 

Note that I'm using lodash, but you can just use Array.forEach()

I effectively create a filter that looks like this combining filter described in the filtering documents :

 [ "all", ["!=", "id", "routeIDHere"], ["!=", "id", "routeIDHere"], ... ] 

This excludes all routes with the identifiers I specified. In your case, I think you want to have something like

 [ "all", ["!=", "type" "YourTypeNameHere"] ... ] 
+2
source

Source: https://habr.com/ru/post/1245329/


All Articles