What is the proper way to select and style markers on Mapbox GL JS? - mapbox

I am working with a Mapbox map that has points. I would like to know the correct procedure for adding a marker-symbol. Here is my GeoJSON:
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-89.12312324,
13.686886
]
},
"properties": {
"title": "Random Location",
"description": "Individual"
}
}
]
Here is an example from the Mapbox docs:
map.addLayer({
"id": "airport",
"source": "airports",
"source-layer": "ne_10m_airports",
"type": "symbol",
"layout": {
"icon-image": "airport-15",
"icon-padding": 0
},
"filter": ["in", "abbrev", ""]
});
When I use this
"layout": {
"icon-image": "marker-11",
"icon-allow-overlap": true,
}
I get little brown dots instead of the classic marker.
I am using
<script src='https://api.mapbox.com/mapbox-gl-js/v0.18.0/mapbox-gl.js'></script>
<link href='https://api.mapbox.com/mapbox-gl-js/v0.18.0/mapbox-gl.css' rel='stylesheet' />
and I am using the
style: 'mapbox://styles/mapbox/outdoors-v9', //stylesheet location
My entire script looks like this:
mapboxgl.accessToken = 'pk.mylongAkey';
var map = new mapboxgl.Map({
container: 'map', // container id
style: 'mapbox://styles/mapbox/outdoors-v9', //stylesheet location
center: [-88.866245, 13.770391], // starting position
zoom: 6 // starting zoom
});
var url = '/maps/index.json';
var source = new mapboxgl.GeoJSONSource({
data: url
});
map.on('load', function () {
map.addSource('location', source);
map.addLayer({
"id": "map",
"type": "symbol",
"source": "location",
"source-layer": 'location',
"layout": {
"icon-image": "marker-11",
"icon-allow-overlap": true,
}
});
});
map.on('click', function (e) {
var features = map.queryRenderedFeatures(e.point, { layers: ['map'] });
if (!features.length) {
return;
}
var feature = features[0];
// Populate the popup and set its coordinates
// based on the feature found.
var popup = new mapboxgl.Popup()
.setLngLat(feature.geometry.coordinates)
.setHTML(feature.properties.title)
.addTo(map);
});
// Use the same approach as above to indicate that the symbols are clickable
// by changing the cursor style to 'pointer'.
map.on('mousemove', function (e) {
var features = map.queryRenderedFeatures(e.point, { layers: ['map'] });
map.getCanvas().style.cursor = (features.length) ? 'pointer' : '';
});
Am I missing something? Also, the popups don't popup above the points, they popup over top of the icon. You can't tell with this little brown dot, but with the rocket for example the popup is in the middle of the rocket. Thanks!
Here is a screenshot

I am working with a Mapbox map that has points. I would like to know the correct procedure for adding a marker-symbol. Is it better to do it in the GeoJSON like:
...
Or is better to use layout like this:
...
Embedding style information in the GeoJSON (the former) is a specification called simplestyle, which is not supported in GL JS. Using layout (the latter) is the only way to style features in GL JS.
I get little brown dots instead of the classic marker.
Could you please provide a screenshot of this?

In the Mapbox Studio Editor, you need to make sure that you actually have an icon called "marker-11" in your icon library. If not, it doesn't know what you are referencing and will default to a dot.
Otherwise, everything else looks fine.

Related

Mapbox popup displays "unknown" instead of properties

After clicking on a street (which is supposed to display a popup with properties), the popup displays "unknown". What should be done to make the popup show the properties? If anyone knows what to change or what could be the cause of the popups not working, I would be really grateful!
<div class="container" style="background-color:#F6F3F3">
<div id='map' style='width: 100%; height: 900px;'></div>
<script>
mapboxgl.accessToken =
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/bisqpski/cjssto8kw77g11gk4rwur575q'
});
map.on('load', function() {
// Add a layer showing the state polygons.
map.addLayer({
'id': 'kazimierz-tileset',
'type': 'fill',
'source': {
"type": "Feature",
"properties": {
"Street": "Świętego Wawrzyńca",
"Probability": "13%"
},
"geometry": {
"coordinates": [
[19.944511, 50.049316],
[19.94617, 50.049681],
[19.946307, 50.049719],
[19.947699, 50.050025],
[19.948851, 50.050282],
[19.949689, 50.050456],
[19.951076, 50.05076],
[19.951401, 50.050831]
],
"type": "LineString"
}
}
});
// When a click event occurs on a feature in the states layer, open a popup
at the
// location of the click, with description HTML from its properties.
map.on('click', 'kazimierz-tileset', function(e) {
new mapboxgl.Popup()
.setLngLat(e.lngLat)
.setHTML(e.features[0].properties.name)
.addTo(map);
});
// Change the cursor to a pointer when the mouse is over the states layer.
map.on('mouseenter', 'kazimierz-tileset', function() {
map.getCanvas().style.cursor = 'pointer';
});
// Change it back to a pointer when it leaves.
map.on('mouseleave', 'kazimierz-tileset', function() {
map.getCanvas().style.cursor = '';
});
});
</script>
</div>
You don't have name as a property for your features. Only street and probability. So you're calling a property that doesn't exist. Use street or define the property name with whatever you want.
"properties": {
"Street": "Świętego Wawrzyńca",
"Probability": "13%"
"Name": "Your Name Here"
},
Or just use the street property.
.setHTML(e.features[0].properties.Street)
Snippet:
<div class="container" style="background-color:#F6F3F3">
<div id='map' style='width: 100%; height: 900px;'></div>
<script>
mapboxgl.accessToken =
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/bisqpski/cjssto8kw77g11gk4rwur575q'
});
map.on('load', function() {
// Add a layer showing the state polygons.
map.addLayer({
'id': 'kazimierz-tileset',
'type': 'fill',
'source': {
"type": "Feature",
"properties": {
"Street": "Świętego Wawrzyńca",
"Probability": "13%"
},
"geometry": {
"coordinates": [
[19.944511, 50.049316],
[19.94617, 50.049681],
[19.946307, 50.049719],
[19.947699, 50.050025],
[19.948851, 50.050282],
[19.949689, 50.050456],
[19.951076, 50.05076],
[19.951401, 50.050831]
],
"type": "LineString"
}
}
});
// When a click event occurs on a feature in the states layer, open a popup
at the
// location of the click, with description HTML from its properties.
map.on('click', 'kazimierz-tileset', function(e) {
new mapboxgl.Popup()
.setLngLat(e.lngLat)
.setHTML(e.features[0].properties.Street)
.addTo(map);
});
// Change the cursor to a pointer when the mouse is over the states layer.
map.on('mouseenter', 'kazimierz-tileset', function() {
map.getCanvas().style.cursor = 'pointer';
});
// Change it back to a pointer when it leaves.
map.on('mouseleave', 'kazimierz-tileset', function() {
map.getCanvas().style.cursor = '';
});
});
</script>
</div>
Lastly, in your example you're adding a layer. But you already have that layer added with the same name in the style you created. You don't need to add it again or you'll get a Error: Layer with id "kazimierz-tileset" already exists on this map since it will naturally pull directly from the style. Make sure to rename the layer or remove the addLayer.

Mapbox GL JS and GeoJSON as an external file

I have code to set markers with Mapbox map
$(function() {
mapboxgl.accessToken = 'pk.###';
var map = new mapboxgl.Map({
container: 'map-global',
style: '..'
});
var geojson = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"title": "POI Title"
},
"geometry": {
"type": "Point",
"coordinates": [0, 0]
}
}
]
};
geojson.features.forEach(function(marker) {
// create a HTML element for each feature
var el = document.createElement('div');
el.className = 'marker';
new mapboxgl.Marker(el)
.setLngLat(marker.geometry.coordinates)
.setPopup(new mapboxgl.Popup()
.setHTML(marker.properties.title))
.addTo(map);
});
});
And it works fine. But I want to use GeoJSON as an external file:
var geojson = 'file.geojson';
And here I have a problem — it doesn't work:
TypeError: undefined is not an object (evaluating '"map.geojson".features.forEach')".
Is there any way to use external GeoJSON file with custom HTML
markers?
You can load external geojson files with plain mapbox addSource().
map.on('load', function() {
var url = 'http://your_geojson_file.com/some_file.geojson';
map.addSource('source_id', { type: 'geojson', data: url});
});
See this example:
https://www.mapbox.com/mapbox-gl-js/example/live-geojson/
Since you are using Jquery, you could use getJSON to load your file:
Load JSON-encoded data from the server using a GET HTTP request.
Reference: http://api.jquery.com/jquery.getjson/
Example:
$.getJSON('file.geojson', function (geojson) {
geojson.features.forEach(function (marker) {
// etc
});
});

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

Adding custom points to mapbox studio

In Mapbox studio classic, you just click where you want a new "marker" and it creates one. I want to do the same thing in the new mapbox studio but that feature doesn't seem to exist. Please note, I do not have a dataset to upload, I need to create a dataset through Mapbox Studio.
If anybody has any insight for me that would be super!
You can add your data to Mapbox Studio along with this custom svg marker. I styled it similar to the old Leaflet L.marker: https://github.com/Ccantey/icons/blob/master/svgs/placeMarker-Blue-Shadow.svg
Then in the layout properties you can set "marker-symbol"/"icon-image" to "myMarker-Blue-Shadow":
map.addSource("pointclick", {
"type": "geojson",
"data": {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [e.lngLat.lng, e.lngLat.lat]
},
"properties": {
"title": "mouseclick",
"marker-symbol": "myMarker-Blue-Shadow"
}
}
});
map.addLayer({
"id": "pointclick",
type: 'symbol',
source: 'pointclick',
"layout": {
"icon-image": "{marker-symbol}",
"icon-size":1,
"icon-offset": [0, -13]
},
"paint": {}
});

can't implement L.mapbox.simplestyle with geoJson

I'm trying to implement simplestyle's options for marker size and color , but can't get them to render. In this simple test case, I'm trying to follow Mapbox's own example quite closely:
var myData = [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [4.509373,51.932994]
},
"properties": {
"marker-size": "large",
"marker-color": "#ffcc00"
}
}
];
var map = L.mapbox.map('map', 'examples.map-20v6611k')
.setView([51.932994,4.509373], 8);
L.geoJson(myData, { style: L.mapbox.simplestyle.style }).addTo(map);
fiddle
But the marker renders in default style. What am I missing?
OK, I've got it working using this extended function from this page of Mapbox's documentation:
L.geoJson(myData, {
pointToLayer: L.mapbox.marker.style,
style: function(feature) { return feature.properties; }
}).addTo(map);
The other Mapbox example didn't make it look like the pointToLayer argument was required, but whatever works:
fiddle
Another alternative would be to create a featureLayer based on your myData:
var featureLayer = L.mapbox.featureLayer(myData).addTo(map);
Your data will have to be an object, however, and not an array:
var myData = {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [4.509373,51.932994]
},
"properties": {
"marker-size": "large",
"marker-color": "#ffcc00"
}
};