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.
Related
I'm trying to plot a supplied vector tile layer onto a map using MapBox GL JS. I've followed the documentation here but nothing apart from the basic map is being output and there are no console errors. In the browser's Network tab I can see lots of .pbf requests being returned with data so it would seem that the endpoint is passing data back, but I don't know how to determine what the problem is in plotting that data onto the map.
The code is as follows:
mapboxgl.accessToken = '[my access token]';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v10',
zoom: 6,
center: [-0.118092, 51.509865]
});
map.once("load", () => {
map.addSource("ncn", {
type: "vector",
tiles: [
"https://tiles.arcgis.com/tiles/1ZHcUS1lwPTg4ms0/arcgis/rest/services/NCN_Vector_Tile_Package/VectorTileServer/tile/{z}/{y}/{x}.pbf"
]
});
map.addLayer({
id: "ncn-lines",
type: "line",
source: "ncn",
"source-layer": "NCN_Vector_Tile_Package",
"layout": {
"visibility": "visible"
},
'paint': {
'line-color': 'rgb(255, 0, 0)'
}
});
});
I am fairly sure that the type should be line (rather than fill) as the data is supposed to contain route lines rather than vector shapes.
I don't have access to the Arcgis server so can't see how anything is configured at that side. Can anyone suggest what might be wrong here and/or how to debug?
It looks like the value for source-layer is not correct - it should be NCN_2020. Here's a demo showing it working: https://jsbin.com/xunuhibuki/1/edit?html,output
How do you get that value? I'm not quite sure the best way, but the way I found: add ?f=html to your vector tile layer like this: https://tiles.arcgis.com/tiles/1ZHcUS1lwPTg4ms0/arcgis/rest/services/NCN_Vector_Tile_Package/VectorTileServer/?f=html then click "Styles" link at the bottom which gives you an example of how to construct your map.addLayer() commands in your mapboxgl code.
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.
I followed
https://medium.com/#mrgrantanderson/https-medium-com-serving-vector-tiles-from-django-38c705f6
to serve the mvt tiles to the mapbox from geoDjango.
With running query
cursor.execute("SELECT ST_AsMVT(tile) FROM (SELECT osm_id, building, ST_AsMVTGeom(geom, TileBBox(%s, %s, %s, 3857)) FROM nepal_khokanabuildings ) AS tile", [zoom, x, y])
as my model project is ESPG:3857
The Vectors don't seem to load up on the map, the api request is working fine.
I also tried serving vector files from Geoserver no luck either.
Here is my JS File
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v10',
zoom: 12,
center: [85.294688,27.634106],
});
var mapillarySource = {
type: 'vector',
tiles: [
'http://0.0.0.0:8000/nepal/api/v1/data/nepal/{z}/{x}/{y}.mvt'
],
minzoom: 0,
maxzoom: 14
};
map.on('load', function() {
map.addSource('mapillary', mapillarySource);
map.addLayer({
'id': 'mapillary',
'type': 'fill',
'source': 'mapillary',
'source-layer': 'water',
'paint': {
"fill-color": "#00ffff"
}
});
});
map.addControl(new mapboxgl.NavigationControl());
</script>
There are lots of problems that can manifest themselves as "my layers don't show".
You can check each of these things:
is the layer being created before the map is ready? (wait for "load" event)
are the correct tile requests being generated?
are those requests succeeding?
are they returning actual .pbf files?
do they contain data in the right location, and in the right projection?
do they contain a layer with the name you expect? ('water' in this case)
do they contain data of the type you expect? (polygons in this case)
I am curious about the 0.0.0.0 host, but also suspect that the layer name may not be right.
If your tile requests are succeeding, you can try using https://stevage.github.io/vector-inspector/ to inspect them, although you may have issues with that page being served on HTTPS and your local tiles being on HTTP.
Use Following ,
"id": "postgis-tiles-layer",
"source-layer": "default",
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.
I am initializing mapbox map by adding sources and layers linked to them.
mapbox.addSource(MY_SOURCE, {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': [],
},
});
mapbox.addLayer({
'id': MY_LAYER,
'type': 'circle',
'source': MY_SOURCE,
'paint': {
'circle-radius': 6,
'circle-color': '#d31467',
},
});
my goal being - I want to have those definitions done once and then - if I need to update the source I just:
mapbox.getSource(MY_SOURCE).setData(geojson);
Sometimes though I need to wipe out all polygons, all points, everything. How can I do that without losing all those definitions? I can only see .removeSource, .removeLayer - which tells me I will actually need to recreate those definitions.
Is there a less destructive way of doing it?
You have two options here:
Hide the layers
map.setLayoutProperty(<layer-id>, 'visibility', 'none');
Remove all features from you sources by setting an empty geojson
map.getSource(<source-id>).setData({
type: 'FeatureCollection',
features: [] // <--- no features
});
Also removing & re-adding the sources and layers might not be the worst option, depending on the frequency you want to do this.