Display custom icon marker from Mapbox vector tiles - mapbox-gl-js

I am using mapbox gl javascript. I have a large geojson data which contains point location (Latitude, Longitude) pair along with some properties. I want to load the large geojson into mapbox studio, and convert it into vector tiles.
Next important task for me is to load the vector tileset using mapbox gl javascript and show custom marker icon for the points in vector tiles. Can you please suggest how can I do that ?

The custom markers setting are explained here : https://docs.mapbox.com/mapbox-gl-js/example/custom-marker-icons/
There are differents ways to display your tileset with its markers. Could you be more precise on what you are trying to do ? Do you want to display them from a web page ?
Meanwhile, you can try to upload you GeoJSON in a new tileset in your Mapbox Studio account. Then create a new style > new layer > select data from your tileset.
At this point, you put your data on Symbol type, then go to style > icon and select your custom icon you previously upload from the Images button at the right top of the editor.
Bon courage,
N.

Please have a look at the answer on my code block to load custom image for a layer.
Note:
I am using vector data source.
Source data consists of points (Lat Lng pair).
Attached image is for reference.
enter image description here
map.addSource('ccc_location', {
type: 'vector',
url: 'mapbox://aciapprover111.4jkdyq5t'
});
map.loadImage('#Url.Content("~/Content/assets/img/green.png")', function (error, green) { //this is where we load the image file
if (error) throw error;
map.addImage("custom-green", green); //this is where we name the image file we are loading
map.addLayer({
'id': 'CCCLocations_VGO',
'type': 'symbol',
'source': 'ccc_location',
"filter": ["all", ["==", "type", "VGO"]],
'source-layer': 'CCCLocations-bgcof4',
'layout': {
'icon-image': "custom-green",
'icon-size': 0.65,
'icon-allow-overlap': true
}
});
});

A good place to start is working through some of the Mapbox-GL-JS examples, and reading the documentation.

Related

Mapbox studio - png labels layer - transparency showing up as black

I have created some custom styles in mapbox studio. They are essentially just the mapbox outdoors style and the mabpox satellite style, each customized, separated out into 2 styles each: the basemap with no labels at all, and only the labels without the basemap. I want to give the user the ability to toggle layers on and off, or set the transparency. You can see the layers here:
Outdoors labels only
Satellite labels only
Within mapbox studio, the tiles show transparency where there are no roads / labels / etc. This is what I would expect. I am then using these layers in leaflet like so:
var mapBoxOutdoorsLabels = L.tileLayer(
'https://api.mapbox.com/styles/v1/slutske22/ck87tp2fq0rq41iqox69g4ko5/tiles/256/{z}/{x}/{y}#2x?access_token={accessToken}',
{ accessToken ,maxZoom: 18, pane: 'labels'})
.addTo(map1)
var mapBoxSatelliteLabels = L.tileLayer(
'https://api.mapbox.com/styles/v1/slutske22/ck8i7fv4h0h771ipc6mwzwmp4/tiles/256/{z}/{x}/{y}#2x?access_token={accessToken}',
{ accessToken ,maxZoom: 18, pane: 'labels'})
.addTo(map2)
As far as I can tell, the way I'm importing these two layers is identical. But for some reason, my labels layer for outdoors shows up properly (with transparent background), while my labels layer for satellite shows up with all black background, and you cannot see through to the basemap. The map on the right is the problem:
Here is a working codesandbox of the problem
I'm not sure what I'm doing wrong in mapbox studio or in my leaflet import for the tiles to be generated with black instead of transparent. The way I'm building the two maps are identical, at least as far as I can tell. Any ideas?
Thanks for reading.
The background layers in your labels mapbox style are not transparent.
Here is a codepen with a copy of your style with the background fixed
What I did:
Removing the /tiles/{x}/{y}/{z}/ part from your style's URL and running that in a browser returns the json from mapbox.
There I saw that your background layer color is missing the alpha channel value.
"layers": [
{
"id": "background",
"type": "background",
"layout": {
"visibility": "none"
},
"paint": {
"background-color": "hsl(222, 56%, 4%)" <= SHOULD BE (222, 56%, 4%, 0)
},
I was able to save the json file and upload it as my own style on https://studio.mapbox.com/
there I changed the alpha channel of the background and reduced the opacity of the satellite layer.
It appears that "visibility: none" doesn't work as intended
exported as a new style, I updated the fork with my style and access token

Deduplicate polygon state/country shared boundaries

I am using GEOJSON to draw a world map with leaflet and having dashed line to draw boundaries, like in below image.
The problem I am having is that the line is not shared by two states if two states share boundaries, rather two lines are drawn each for different state. Due to this when zoomed enough lines looks weird as they get overlapped on each other. As show below.
var GeoJsonLayer = L.geoJson();
var myStyle = {
"color": "#fff",
"weight": 0.8,
"opacity": 1,
"fillOpacity": "1",
"fillColor": "#243E54"
};
// here data.world contains GEOJson to draw whole map
if (data.world) {
GeoJsonLayer.options.className = "geojsonlayerpolygon";
GeoJsonLayer.on("dblclick", function (ev) {
map.fireEvent("dblclick", ev);
});
GeoJsonLayer.addData(data.world);
GeoJsonLayer.setStyle(myStyle);
}
For making it dashed line i am using below CSS
.geojsonlayerpolygon{
stroke-dasharray: 6 4;
}
GEOJson I am using is
https://jsonblob.com/826f1a94-c1a3-11e9-a004-354d7c27cab2
How can i make sure that boundaries, when shared, have only one line?
Sounds like a job for TopoJSON. From its readme file:
TopoJSON is an extension of GeoJSON that encodes topology. Rather than representing geometries discretely, geometries in TopoJSON files are stitched together from shared line segments called arcs. This technique is similar to Matt Bloch’s MapShaper and the Arc/Info Export format, .e00.
TopoJSON eliminates redundancy, allowing related geometries to be stored efficiently in the same file. For example, the shared boundary between California and Nevada is represented only once, rather than being duplicated for both states. A single TopoJSON file can contain multiple feature collections without duplication, such as states and counties. Or, a TopoJSON file can efficiently represent both polygons (for fill) and boundaries (for stroke) as two feature collections that share the same arc mesh.
So, start by loading the topojson library...
<script src="https://unpkg.com/topojson#3"></script>
...then create a topology object for your GeoJSON data; note that TopoJSON expects an array of GeoJSON features, e.g. I'll load a GeoJSON FeatureCollection containing the Natural Earth country boundaries via fetch and create a topology:
fetch("ne_110m_admin_0_countries.geojson")
.then(res=>res.json())
.then(json=>{
var topo = topojson.topology([json]);
/* ...more stuff here soon */
});
...then add a L.GeoJSON layer with just the polygon fill, setting the stroke option to avoid drawing any lines on the contour of the polygons (remember that path styling options can be passed to GeoJSON constructors) ...
var layerFill = L.geoJson(json, { stroke: false }).addTo(map);
...calculate the mesh of the topology, which will be a GeoJSON MultiLineString...
topojson.mesh(topo);
...and create another L.GeoJSON instance to draw said MultiLineString. Style the lines as you like (including dashArray), e.g. ...
var layerLines = L.geoJson(topojson.mesh(topo), {
fill: false, dashArray:[3, 6], weight: 2
}).addTo(map);
The end result, which you can see here as a working example, contains no overlapping dashed lines, as expected:
Using TopoJSON is one possible approach. There are other possible approaches (e.g. pre-generating a MultiLineString GeoJSON file with just the boundaries, using a different tool, etc); but the idea of using topological rules on the dataset would be the same.

Transparent vectortiles

Background
I am playing around with mapbox and uploaded a shapefile from which I created a vector tileset. I loaded the tileset into mapxbox studio to create a custom style. My aim is to solely display the vector tileset with no background layer at all. I am doing this for the reason because I want to overlay the tileset over another raster tileset via leaflet later on. In mapbox studio this looks as follows - you can see the colored vectors and the surrounding transparent area:
Problem:
When I try to visualize both tilesets via leaflet, I am not able to see through the first tileset. Instead I am seeing my colored vector with a black background:
Any chance I can make the tileset background transparent? So the vectors wont be surrounded by a black background anymore but rather by the underlying raster tile set?
Here some code snippets I am using:
<div id='map'>
</div>
<script>
var sat = L.tileLayer('https://api.mapbox.com/styles/v1/xxx/xxx/tiles/256/{z}/{x}/{y}?access_token=xxx', {
attribution: 'Raster tile set'
});
var clc = L.tileLayer('https://api.mapbox.com/styles/v1/xxx/xxx/tiles/256/{z}/{x}/{y}?access_token=xxx', {
attribution: 'Transparent vector tile set'
});
var map = L.map('map', {
center: [48.2, 16.37],
zoom: 10,
layers: [sat, clc]
});
</script>

Using Mapzen tiles with Leaflet

My reading of the Leaflet and Mapzen documentations suggest that in order to use a custom tile provider with Leaflet, one needs to do just two things:
Specify the tile provider in L.tilelayer(urlTemplateToTileProvider)
Set this provider to MapZen
var urlTemplateToTileProvider =
'http://tile.mapzen.com/mapzen/vector/v1/all/{z}/{x}/{y}.mvt?api_key=apiKey'
However, when I try this I end up with an empty map which then proceeds to display markers etc correctly. And yet a manual test for a generated tile URL, e.g.
http://tile.mapzen.com/mapzen/vector/v1/all/14/8471/5583.mvt?api_key=apiKey
did in fact download some - unintelligible to me - data.
I also tried using the other two formats mentioned in the Mapzen docs (.json and .geojson) but with exactly the same result. Given that the latter two formats return human readable data, I checked them out for my test tile in my browser and the data is indeed for the area I want to use.
Curiously enough, the Leaflet docs and tutorials request a PNG tile layer (http://{s}.tile.osm.org/{z}/{x}/{y}.png), not raw data.
What am I doing wrong here?
The Tile Layer is for raster tiles (i.e. plain images, like the PNG format for example).
Mapzen delivers vector tiles. To use them with Leaflet, you could use a plugin, e.g. Leaflet.VectorGrid (license)
Display gridded vector data (sliced GeoJSON or protobuf vector tiles) in Leaflet 1.0.0
See the demo, which includes tiles from Mapzen
var mapzenTilesUrl = "https://tile.mapzen.com/mapzen/vector/v1/all/{z}/{x}/{y}.mvt?api_key={apikey}";
var mapzenVectorTileOptions = {
rendererFactory: L.canvas.tile,
attribution: '© MapZen, © OpenStreetMap contributors',
vectorTileLayerStyles: vectorTileStyling,
apikey: 'KEY',
};
var mapzenTilesPbfLayer = L.vectorGrid.protobuf(mapzenTilesUrl, mapzenVectorTileOptions);
Since you have raw data in the vector tiles, you need to provide the styling spec (vectorTileStyling)

How to fill custom area in mapbox?

I have following map in mapbox editor:
Is it possible to fill custom area of the map ? (in this example, area is selected, I can see its attributes)
How can I do it?
You'll want to filter the data and then polygon styles to style the layer.
For instance, if the ID you can rely on is ID_0, then
#GEO_adm2[ID_0 = 81] {
polygon-fill:#f00;
}