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

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.

Related

In Mapbox GL JS, can you pass coordinates to an external GeoJSON data source?

Can you pass coordinate values as variables when trying to retreive an external GeoJSON data source? Ideally I'd like to pass something like this, but it doesn't work for me.
map.addSource('geojsonpoints', {
type: "geojson",
data: 'http://myexample.com/pins?lat={lat}&lon={long}'
});
I am able to pass Z, X, Y coordinates if I use Map Vector Tiles (mvt) as a source. i.e. This works:
map.addSource('mapvectortiles', {
'type': 'vector',
'tiles': ['http://myexample.com/{z}/{x}/{y}'],
But I haven't figured out how to do it for a GeoJSON source. Anyone have any ideas if it is possible in n Mapbox GL JS?
FYI, I am able to generate the URL using the method below, but the problem is it doesn't refresh when I move the map, unlike vector tiles.
var lng = map.getCenter().lng
var lat = map.getCenter().lat
var url = 'http://myexample.com/pins?lat='+lat+'&lon='+lng
map.addSource('EPC', {
type: "geojson",
data: url
});
I use GeoJSON to draw Tiles on the map
this is a sample GeoJSON:
{ "type": "FeatureCollection",
"features": [
{ "type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[4.342254780676343, 50.89533552689166],
[4.342254780676343, 50.89443721160754],
[4.340830581474948, 50.89443721160754],
[4.340830581474948, 50.89533552689166],
[4.342254780676343, 50.89533552689166]
]
]
},
"properties": {}
}
]
}
after all you have to add the source and add the layer
add Source:
const sourceJson: GeoJSONSourceRaw = {
type: 'geojson',
data: data as FeatureCollection
};
map.addSource(sourceId, sourceJson)
data is your json file
add Layer:
const layer: FillLayer = {
id: sourceId,
source: sourceId,
type: 'fill',
paint: {
'fill-color': color,
'fill-opacity': opacity
}
}
this.map.addLayer(layer);
There are two parts to your question:
Update the data source when the map is moved
Use the map's extent as part of the GeoJSON source's URL.
You have part 2 under control, so:
Update the data source when the map is moved
Use map.on('moveend', ...
Use map.getSource(...).setData(...)

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

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

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.

querySourceFeature returns empty array

I am using mapbox to try and query all features of the mapbox tileset and return them as geojson. From what I understand, to query features that are no visible on the screen, you must use querysourcefeatures. My tileset only shows up at zoom 14 so I am having trouble querying all the features in the dataset at once and then applying a filter. Is this possible? It stills like querySourceFeatures returns an empty array.
function addLayers() {
map.addSource('plutonew-c03oxi', {
'type': 'vector',
'url': 'mapbox://samtpr.4ehwzn0r'
});
map.addLayer({
"id": "parcels_fill",
"type": "fill",
"source": "plutonew-c03oxi",
"source-layer": "plutonew-c03oxi",
'layout': {
'visibility': 'visible'
},
paint: {
'fill-color': 'blue',
'fill-outline-color': 'gray',
"fill-opacity": ["case",
["boolean", ["feature-state", "hover"], false],
0.5,
0
]
}
});
var features = map.querySourceFeatures('plutonew-c03oxi', {filter: ["==", ['get','ZIPCODE'], zipcode_val]});
From what I understand, to query features that are no visible on the screen, you must use querysourcefeatures
You may have misunderstood. querySourceFeatures allows you to query features that are present within the vector tiles currently loaded and displayable within the current viewport and zoom level. Unlike queryRenderedFeatures they don't have to actually be rendered through a visible layer, however.
In this case it sounds like you're hoping to gain access to features that are not available at the current zoom level, which is not possible.

Difference between leaflet Marker and mapbox featureLayer

I understood that I can use the general Leaflet layer, and the more advanced map-box featureLayer, that provides useful functions as the filter.
However, I don't understand the difference between
marker = L.Marker (new L.LatLng(lat, lng),
{
icon: L.mapbox.marker.icon(
{'marker-color': 'fc4353'
'marker-size': 'large'
}),
title: name,
});
map.addLayer(marker);
and
var poijson = {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [lng, lat]
},
"properties": {
"title": poi.name,
"marker-color": "#fc4353",
"marker-size": "large"
}
};
map.featureLayer.setGeoJSON(geojson);
Is it just the same?
[UPDATE]
Moreover, if I had many markers, should I add a new layer for each marker? It seems not a good thing for performance..
For instance, If I do:
var pois; //loaded with pois info
var geojson=[]; //will contain geojson data
for (p=0; p< pois.length; p++)
{
var poi = pois[p];
var poijson =
{
"type": "Feature",
"geometry":
{
"type": "Point",
"coordinates": [poi.lng, poi.lat]
}
};
geojson.push(poijson);
}
map.featureLayer.setGeoJSON(geojson);
Does it will create many layers for each poi, or just one layer with all the markers?
thank you
When you add a marker to a Leaflet map via map.addLayer(marker);, the marker is added to the 'leaflet-maker-pane'. The markers are plain images/icons.
You can use a geoJSON layer to draw GIS features: points, lines, polygons, etc.
See here: http://leafletjs.com/examples/geojson.html
Mapbox's featureLayers is just an extension to Leaflet's geoJSONLayer
To add multiple markers, call addMarker multiple times. Leaflet will create a new layer for each of the markers. Each marker will be added as an image element to the leaflet-marker-pane div:
http://bl.ocks.org/d3noob/9150014
Updated response:
If you add a GeoJSON layer with multiple features, Leaflet will create separate layer for each of the features. You can inspect the layers of the map by calling map._layers after adding the GeoJSON Layer.
marker.addTo(map) and map.addLayer(marker) are doing the same thing.
Here's the addTo function taken from the source
addTo: function (map) {
map.addLayer(this);
return this;
},