React-Map-GL: How can i see the icons which i can use by default mapbox - map sprite? - mapbox

I have the following geojson of points, which are going to be buses on the map:
const features = buses.map((el) => ({
type: 'Feature',
geometry: {
type: 'Point',
coordinates: el.state.position.coordinates.map((coordinate) => +coordinate),
},
properties: {
reg_number: el.reg_number,
object_id: el.object_id,
route: el.route,
fuel: +el.state.fuel,
speed: +el.state.speed,
},
}));
return features;
}
and it's layer is as follows:
id: 'Point-data',
type: 'circle',
paint: {
'circle-color': {
property: 'percentile',
stops: [
[10, "#ff0000"],
[20, '#ff3300'],
[30, "#ff6600"],
[40, "#ff9100"],
[50, '#ffd000'],
[60, '#bbff00'],
[70, '#b3ff00'],
[80, '#91ff00'],
[90, '#7bff00'],
[100, '#1eff00']
],
},
'circle-radius': 7,
},
};
instead of 'circle' i want to use 'symbol' type and set an icon. As far as i know, it needs a name from map style sprite icon collection. I don't need to make a custom sprite right now, i think i will be satisfied with default bus icon, which dark mapbox map for sure has in sprite, but i don't know how to find it. Where can i see the list of icons and their names of sprite? and the png and json files it consist of.example of sprite from Uber Open Source

For the others i would like to share the solution i found by myself:
i created a map in https://studio.mapbox.com and then followed documentation: https://docs.mapbox.com/api/maps/#sprites
Particulary this:
curl "https://api.mapbox.com/styles/v1/{username}/{style_id(take it from the url of the map u created)}/sprite.{format(png or json)}?access_token={your mapbox access token}
There i found bus icon. I made a symbol layer, where i put the name of the icon in the 'icon-image'. I hope it will help smb.

Related

Mapbox GL JS Change the fill-color's property value based on an expression

I have a chloropleth map with a geojson data source backing it. The data set contains data for each country for two different years, with the fill color based on one of the properties in the JSON. Here is my addLayer code currently, which works fine.
map.addLayer({
id: 'emissions',
type: 'fill',
source: {
type: 'geojson',
data: './data.json'
},
paint: {
'fill-color': {
property: 'total_2014',
type: 'exponential',
base: 0.99999,
stops: [
[3, "hsl(114, 66%, 53%)"],
[2806634, "hsl(0, 64%, 51%)"]
]
},
'fill-opacity': 1
}
});
I would like to be able to programatically switch the json property on which the fill color is based, and an expression seems the obvious way to do so, however the following code fails with the error layers.emissions.paint.fill-color.property: string expected, array found.
...
paint: {
'fill-color': {
property: ['get', propName], // propName var is e.g. 'total_2014'
type: 'exponential',
base: 0.99999,
stops: [
[3, "hsl(114, 66%, 53%)"],
[2806634, "hsl(0, 64%, 51%)"]
]
},
'fill-opacity': 1
}
...
Is there a way to achieve what I'm aiming for? I'm very new to using Mapbox GL JS, so apologies if this is a basic question.
Just in case anyone else happens across this requirement, I found a workaround by updating the map's style property directly. This isn't an exact answer since the approach doesn't use expressions, but the performance of mapbox diffing source and applying the changes is very fast and meets my requirements.
function loadDataForYear(year) {
const style = map.getStyle();
style.layers.find(({ id }) => id === "emissions").paint['fill-color']['property'] = 'total_' + year;
map.setStyle(style);
}

Mapbox GL JS interactivity on a Warehouse Floorplan as the base map plausible?

I am trying to figure out if Mapbox GL JS would be applicable or fit for my use case:
My base map example has to be made of several components of a warehouse instead of Geospatial map
I would like to display a clustering layer representing, for example, the number of products stored at a particular shelf/section in the warehouse.
Each box/product in the warehouse would be represented as a pinpoint and while zooming out, collection of products/boxes would be represented as a cluster.
With that said, I'm aware 2) and 3) would be supported in case of a geospatial map but my concern is aimed at an customized non-geospatial map, if applicable.
Geospatial or not, it all boils down to coordinates. Mapbox GL JS expects geographic coordinates, so you just need to carve out a portion of the coordinate range (-180 thru 180 on the x axis, -90 to 90 on the y axis) that will meet your needs, and make sure you have good coordinates for the shelves or wherever you need to visualize clusters.
Here's a codepen that shows a simple mapbox style with only a background and a rectangle. No streets, no rivers, no labels...
const map = (window.map = new mapboxgl.Map({
container: "map", // container ID
// Choose from Mapbox's core styles, or make your own style with Mapbox Studio
style: {
version: 0,
name: "Foo",
sources: {
"building-outline": {
type: "geojson",
data: {
type: "Feature",
properties: {},
geometry: {
type: "Polygon",
coordinates: [
[
[0, 0],
[60, 0],
[60, 30],
[0, 30],
[0, 0]
]
]
}
}
}
},
layers: [
{
id: "background",
type: "background",
paint: {
"background-color": "steelblue"
}
},
{
id: "building-fill",
type: "fill",
source: "building-outline",
paint: {
"fill-color": "#ccc"
}
},
{
id: "building-line",
type: "line",
source: "building-outline"
}
]
}, // style URL
center: [30,20], // starting position [lng, lat]
zoom: 2 // starting zoom
}));
https://codepen.io/chriswhong/pen/XWqpPXN
You can also build your own style in Mapbox Studio.

How do I get a single set of country boundaries from Mapbox country boundaries

https://codepen.io/m12n/pen/XWNRZMg?editors=0010
mapboxgl.accessToken =
"pk.eyJ1IjoiaW50ZWxsaWdlbmNlZnVzaW9uIiwiYSI6ImNrM2l2cnk1NzBibGIzbm5yaHNycXltZmYifQ.tPEnnW5NAPmInCJDYVfJxA";
var map = new mapboxgl.Map({
container: "map",
style: "mapbox://styles/mapbox/dark-v10",
zoom: 8,
center: [-71.4935, 41.5852]
});
map.on("load", function () {
map.addSource("countries-no-simplification", {
type: "vector",
url: "mapbox://mapbox.country-boundaries-v1"
});
map.addLayer({
id: "countries-simplification-data",
type: "fill",
source: "countries-no-simplification",
"source-layer": "country_boundaries",
paint: {
"fill-color": "#ff69b4",
"fill-opacity": 0.3
}
});
});
The above code and pen shows usage of the MapBox county boundaries where I fill the layer with a colour and a low opacity.
Because the source has multiple world views I get both boundaries for disputed countries showing at the same time, and therefore get the effect shown (stronger colouring).
Eventually I actually want to apply a colour based on a specific datapoint, but for now I would be happy with being able to render only a single set of boundaries (a single world view?).
I cant seem to figure out how to get only one such set of boundaries from the source.
You can apply a filter to keep the boundaries of a specific world view (US, CN, IN, etc.) and remove disputed boundaries. Example:
map.addLayer({
id: "countries-simplification-data",
type: "fill",
source: "countries-no-simplification",
"source-layer": "country_boundaries",
filter: [
'all',
['match', ['get', 'worldview'], ['all', 'US'], true, false],
["!=", "true", ["get", "disputed"]],
],
paint: {
"fill-color": "#ff69b4",
"fill-opacity": 0.3
}
});

How to display stacked locations in a mapbox layer?

I'm very new to mapboxgl and trying to create a map that allows users to filter points over time. I customized this tutorial with my data to get the initial map up and running:
https://docs.mapbox.com/help/tutorials/show-changes-over-time/
everything worked really well until I loaded my data and realized that many points shared the same coordinates.
Some googling revealed this answer:
Multiple markers - Same coordinates
Both the idea of using offsets or spidering feel like reasonable solutions. Unfortunately, it is not clear to me how to apply those to the data as I loaded it. I believe that the relevant portion of the script is:
map.on('load', function() {
map.addLayer({
id: 'year',
type: 'circle',
source: {
type: 'geojson',
data: './grandpascan.geojson' // replace this with the url of your own geojson
},
paint: {
'circle-radius': [
'interpolate',
['linear'],
['number', ['get', 'Pages']],
0, 4,
5, 24
],
'circle-color': [
'interpolate',
['linear'],
['number', ['get', 'Pages']],
0, '#2DC4B2',
1, '#3BB3C3',
2, '#669EC4',
3, '#8B88B6',
4, '#A2719B',
5, '#AA5E79'
],
'circle-opacity': 0.8
},
If that is correct, how can I identify those points for styling? They do not appear to be markers that can easily addressed in CSS, although I may be completely misunderstanding how this all fits together.
thanks!
The code here is creating a layer within the map, of type circle. You could offset locations using the circle-translate property.
If you want to use CSS transforms to offset markers, you should create them as Marker objects which exist in HTML, outside the map.

I'm attempting to get zip codes to display within zip code borders

Several moments are happening correctly in this effort, the map is displaying as expected, the zip code boundaries are showing as expected, but I'm not able to figure how to get 5-digit zip codes to be the label within each zip code boundary. Any help (with example code if possible) would be greatly appreciated!
Here's some code:
<html>
<div id='mapdiv'></div>
...
mapboxgl.accessToken='<token>';
var mapobj = new mapboxgl.Map({
container: 'mapdiv',
style: 'mapbox://styles/mapbox/streets-v9',
minZoom: 3,
maxZoom: 20,
zoom: 10,
center: [-105.1613858,39.6791558]
});
<script src="https://api.mapbox.com/mapbox-gl-js/v0.39.1/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v0.39.1/mapbox-gl.css" rel="stylesheet" />
...
mapobj.on('load', function() {
// Add ZipCode source to map
mapobj.addSource('zipSource', {
type: 'vector',
url: 'mapbox://mapbox.enterprise-boundaries-p2-v1'
});
mapobj.showTileBoundaries = true;
// Add hot ZipCode layer to map
mapobj.addLayer({
id: 'hotZipLayer',
type: 'fill',
source: 'zipSource',
'source-layer': 'boundaries_postal_2',
paint: {
'fill-outline-color': 'rgba(0,0,0,1)',
'fill-color': 'rgba(0,0,0,0.01)'
}
});
// Add Zip numbers symbol layer to map
mapobj.addLayer({
id: 'zipCodeLabels',
type: 'symbol',
source: 'zipSource',
'source-layer': 'points_postal_2',
layout: {
'text-field': '{id}',
'text-justify': 'center',
'text-size' : 10
},
paint: {
'text-color': 'black',
'text-halo-color': 'white',
'text-halo-width': 25
}
});
});
And an example data entry:
[
{
"geometry":
{
"type":"Point","coordinates":[-105.0908374786377,39.707747919880916]
},
"type":"Feature",
"properties":
{
"id":"USP280226"
},
"id":2,
"layer":
{
"id":"zipCodeLabels",
"type":"symbol",
"source":"zipSource",
"source-layer":"points_postal_2",
"layout":
{
"text-field":"{id}",
"text-justify":"center",
"text-size":10
},
"paint":
{
"text-color":"black",
"text-halo-color":"white",
"text-halo-width":25
}
}
},...]
So in this case the value that would show up within the zip code boundary is "USP280226", what I would like to appear is "80226", so I would like to call substring(4) on that id value, but I don't see an easy way to do that for each displayed zip code on the map.
I would imagine MapBox has a way to do this properly, but I haven't been able to find it in the docs or examples.
Thanks in advance for any help.
The currently released version of Mapbox-GL-JS doesn't support any kind of functions on data. You will have to process the data offline so that it contains the labels you want to display.
(I think a forthcoming version may support this kind of function, but I'm not certain.)
EDIT The "expression" functionality is now released. Unfortunately I don't think it helps you. There's a concat function but no way to split strings that I can see.