Mapbox GL-JS : Adding new tileset overlay under labels - mapbox

I have a tileset that I am loading into my map (map is called topleftmap). I want the city and other labels to load over the tiles, not under - sort of like in this example from Mapbox : https://docs.mapbox.com/mapbox-gl-js/example/geojson-layer-in-stack/
How do I do this with tilesets? I have an external JS file I use to load in the tilesets like this :
topleftmapbox.addLayer({
"id": "currentProduct",
"type": "raster",
"source": {
"type": "raster",
"tiles": ["tiles/" + productSelection + "/" + productLocation + "/{z}/{x}/{y}.png"],
"minzoom": 8,
"maxzoom": 10,
"scheme": "tms",
"tileSize": 256,
}});
So of course that works fine, but the labels are UNDER the tiles. I have tried this below, (using the example from Mapbox) but it doesn't seem to work :
var layers = topleftmapbox.getStyle().layers;
// Find the index of the first symbol layer in the map style
var firstSymbolId;
for (var i = 0; i < layers.length; i++) {
if (layers[i].type === 'symbol') {
firstSymbolId = layers[i].id;
break;
}
}
topleftmapbox.addLayer({
"id": "currentProduct",
"type": "raster",
"source": {
"type": "raster",
"tiles": ["tiles/" + productSelection + "/" + productLocation + "/{z}/{x}/{y}.png"],
"minzoom": 8,
"maxzoom": 10,
"scheme": "tms",
"tileSize": 256,
},firstSymbolId});
Lastly, here is an image showing what it looks like. My tiles are slightly transparent, but the labels should be bright white, like the ones away from the data. Any thoughts?

You're doing everything right. You just have a slight syntax mistake:
},firstSymbolId});
This should be:
}}, firstSymbolId);

Related

Creating 3rd Party Raster Tiles for Mapbox

I am trying to use Mapbox to integrate high-res drone imagery onto our website. It works well when I create the tiles in Mapbox Studio, but it has a size limit and only accepts 8-bit imagery. I have tried creating my own tiles using gdal2tiles, but they won't load on the map. I'm not sure if this is a compatibility issue, my gdal tiling settings, or a problem with the code itself. Any help would be greatly appreciated!
I have tried modifying the code given by Mapbox for 3rd party raster tiles, but it did not work.
gdal2tiles
gdal2tiles.generate_tiles(infile, outdir, np_processes=4, zoom='0-22', srs='EPSG:3857')
<div id='map'></div>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoibHVrYXNmcmFzZXIiLCJhIjoiY2p5ZnN3Nm12MWZrdDNscW85aHAwbW52eiJ9.fbdPTtQHTUWaLTex9dCO0g';
var map = new mapboxgl.Map({
container: 'map', // container id
style: {
"version": 8,
"sources": {
"raster-tiles": {
"type": "raster",
"tiles": ["./{z}/{x}/{y}.png"],
"tileSize": 256
}
},
"layers": [{
"id": "simple-tiles",
"type": "raster",
"source": "raster-tiles",
"minzoom": 0,
"maxzoom": 22
}]
},
I have tried running this html locally in the same folder as the tiles, and uploading both to our AWS server, but neither works. In both cases the background map loads, but the tiles do not.
gdal2tiles outputs tms tiles and not xyz tiles so try setting a scheme on the source like this:
new mapboxgl.Map({
container: 'map', // container id
style: {
"version": 8,
"sources": {
"raster-tiles": {
"type": "raster",
"tiles": ["./{z}/{x}/{y}.png"],
"tileSize": 256,
"scheme": "tms"
}
},
"layers": [{
"id": "simple-tiles",
"type": "raster",
"source": "raster-tiles",
"minzoom": 0,
"maxzoom": 22
}]
}
});

react-map-gl without API key using osm tiles

Is it possible?
This tells me it is, but dont know why it defines and API key.
but I cannot get it to work with react-map-gl StaticMap class. The property I can see from that class is just mapStyle which would take a standard Mapbox vector tiles path/name. Does it take an object? My code does not give me an error or show the tiles I request.
<DeckGL>
<StaticMap
mapStyle= {{
"version": 7,
"sources": {
"simple-tiles": {
"type": "raster",
"tiles":["http://a.tile.openstreetmap.org/{z}/{x}/{y}.png", "http://b.tile.openstreetmap.org/{z}/{x}/{y}.png"],
"tileSize": 256
},
"power": {
"type": "vector",
"tiles": ["http://gpstrails.info/ex/leaflet/power/osm/{z}/{x}/{y}.json"]
}
},
"layers": [{
"id": "simple-tiles",
"type": "raster",
"source": "simple-tiles",
"minzoom": 0,
"maxzoom": 22
},
{
"id": "road",
"source": "power",
"source-layer": "power",
"type": "line",
"layout": {
"line-join": "round",
"line-cap": "round",
},
"paint": {
"line-color": "red",
"line-width": 4,
}
}]
}}/>
</DeckGL>
Thank you
Edit: from the correct answer, and to keep things in SO, this is the json living on the S3:
{
"version": 8,
"name": "OSM",
"metadata": {
},
"sources": {
"openmaptiles": {
"type": "vector",
"url": "https://free.tilehosting.com/data/v3.json?key={key}"
},
"osm": {
"type": "raster",
"tiles": [
"http://tile.openstreetmap.org/{z}/{x}/{y}.png"
],
"minzoom": 0,
"maxzoom": 14
},
"91y5159eg": {
"type": "vector",
"url": "http://localhost:3000/tilejson.json"
}
},
"sprite": "https://openmaptiles.github.io/klokantech-basic-gl-style/sprite",
"glyphs": "https://free.tilehosting.com/fonts/{fontstack}/{range}.pbf?key=undefined",
"layers": [
{
"id": "osm",
"type": "raster",
"source": "osm"
}
],
"id": "klokantech-basic"
}
UPDATE: Mapbox changed their license in 2.0 so the accepted answer is correct for versions < 2.0. Mapbox > 2.0 will complain if no access_token is provided.
The trick is in the style that's used. A style is a JSON object, whose specification you can read more about here. You can generate custom styles using tools such as Maputnik, a visual editor that generates style-compliant files for use in MapboxGL maps. Once you have an appropriate style generated, you can use it in React Map GL.
Here's what the basic component would look like, as altered from the example in the Github repo:
<ReactMapGL
mapStyle="https://s3.amazonaws.com/cdn.brianbancroft.io/assets/osmstyle.json"
{...this.state.viewport}
onViewportChange={viewport => this.setState({ viewport })}
/>
Note that this is just an abstract example. The tile loads from OSM here are a bit too slow to be useful in production. But it should illustrate how to make maps without relying on the services side of Mapbox.

Drawing a line in mapbox-gl using coordinates from an array?

I am trying to draw a line on mapbox using coordinates from an api request. The api call retrieves an array of map points latitude and longitude values. I had tried using the example for creating a geojson line at this website:
https://www.mapbox.com/mapbox-gl-js/example/geojson-line/ however this example and every other example I found only showed adding layers to the map containing hardcoded coordinates rather than coordinates that will be retrieved from another source later.
What I originally thought would work is simply creating an array of lat/longs in the appropriate format then putting that array equal to the coordinates when adding a layer, like so:
var lineArray = [];
for(var i = 0; i < response.mapPoints.length; i++)
{
lineArray[i] = " [" + response.mapPoints[i].lng + ", " + response.mapPoints[i].lat + "]";
}
map.addLayer({
"id": "route",
"type": "line",
"source": {
"type": "geojson",
"data": {
"type": "Feature",
"properties": {},
"geometry": {
"type": "LineString",
"coordinates": [
lineArray
]
}
}
},
"layout": {
"line-join": "round",
"line-cap": "round"
},
"paint": {
"line-color": "#888",
"line-width": 8
}
});
The lineArray looked correct after printing it out. I was able to create a small line using a for loop and changing the add layer code to look like the following:
"coordinates": [
[ response.mapPoints[i].lng, response.mapPoints[i].lat ],
[ response.mapPoints[i+1].lng, response.mapPoints[i+1].lat ]
]
however this took way too long since I am using thousands of coordinates at a time and am having to loop through every single one in order to draw the line.
Am I on the right track at all? Any help or direction to a similar example would be greatly appreciated!
You could use Turf.js for creating a LineString feature from an array of positions (http://turfjs.org/docs/#lineString) and use this LineString as a source for a line layer:
Example (based on https://www.mapbox.com/mapbox-gl-js/example/geojson-line/):
http://jsbin.com/beziyolisu/1/edit?html,output
var positions =[
[lon_1, lat_1],
...
[lon_n, lat_n]
];
var linestring = turf.lineString(positions);
map.on('load', function () {
map.addLayer({
"id": "route",
"type": "line",
"source": {
"type": "geojson",
"data": linestring
},
"layout": {...},
"paint":{...},
});
});

MapboxGL JS - Shape layer type

I have a map with a vector tile source containing thousands of geojson points.
I can display the points on a map, showing a circle for each one of them, using a circle type layer.
I would like to do the same, but using different shapes, such as square and triangle. Isn't there a built-in way to do this ? What are my options ?
In case it is of any use, this is what I did :
I created a set of svg images in different colors, by editing the maki shape icons provided at https://www.mapbox.com/maki-icons/editor/
I converted them to a jpg sprite file and a json descriptor using https://github.com/mapbox/spritezero-cli
I created a style derived from the mapbox-provided styles, in order to use my custom sprite, and served this style using https://github.com/klokantech/tileserver-gl
In my layer configuration, I used a "symbol" type layer and selected the relevant icon by passing its name in the layout properties "icon-image" : "green-triangle-11"
I'll admit it's quite a lot of work to display a green triangle on a map !
Edit (18-07-2017) : I found out you can load any image and display it on the map, it doesn't have to be part of the style. I'm not sure if Mapbox added this recently or if I had missed it until now. Here goes :
map.loadImage('https://upload.wikimedia.org/wikipedia/commons/thumb/6/60/Cat_silhouette.svg/400px-Cat_silhouette.svg.png', (error, image) => {
if (error) throw error;
map.addImage('cat', image);
map.addLayer({
"id": "points",
"type": "symbol",
"source": {
"type": "geojson",
"data": {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [0, 0]
}
}]
}
},
"layout": {
"icon-image": "cat",
"icon-size": 0.25
}
});
});
Taken from https://www.mapbox.com/mapbox-gl-js/example/add-image/

satellite tile source not working

https://www.mapbox.com/mapbox-gl-style-spec/#sources-raster
This results in black tiles without error message, I have no idea why?
var style = {
"version": 8,
"sprite": "mapbox://sprites/mapbox/bright-v8",
"glyphs": "mapbox://fonts/mapbox/{fontstack}/{range}.pbf",
"sources": {
"mapbox-satellite": {
"type": "raster",
"url": "mapbox://mapbox.satellite",
"tileSize": 256
}
},
"layers": [{
"id": "new-layer",
"type": "background",
"paint": {"background-color": "#111"},
"interactive": true
}],
}
mapboxgl.accessToken = ...
var map = new mapboxgl.Map({
container: 'map',
style: style,
//style: 'mapbox://styles/mapbox/satellite-v8',
center: [4.7095, 52.0393],
zoom: 9,
hash: true
});
It looks like you've only added the raster source. If you want the satellite tiles to be drawn on your map, you must also add a raster layer which uses the raster source. See https://www.mapbox.com/mapbox-gl-style-spec/#layers-raster