Mapbox popup displays "unknown" instead of properties - popup

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.

Related

Hover effect for Countries

SO I am new to Mapbox but I am trying to make countries change color on hover. I have seen the hover tutorial on the Docs for states but I am having difficulty finding the right type, data, and source for countries. I have the Mapbox Countries v1 already added to the map from studio. When I try to run this code I get either that it can't find source:"country_boundaries" or "country-boundaries". I know it's something simple but appreciate the help. Thanks.
var hoveredStateId = null;
map.on('load', function () {
==>>map.addSource('states', {
==>>'type': 'geojson',
==>>'data': 'https://docs.mapbox.com/mapbox-gl-js/assets/us_states.geojson'
});
map.addLayer({
'id': 'state-fills',
==>>'type': 'fill',
==>>'source': 'states',
'layout': {},
'paint': {
'fill-color': '#627BC1',
'fill-opacity': [
'case',
['boolean', ['feature-state', 'hover'], false],
1,
0.5
]
}
});
map.addLayer({
'id': 'state-borders',
==>>'type': 'line',
==>>'source': 'states',
'layout': {},
'paint': {
'line-color': '#627BC1',
'line-width': 2
}
});
Below you will find a complete example I've put together from findings at https://docs.mapbox.com/ and other places on the internet.
Please note that this uses Mapbox example token and http://geojson.xyz/ directly, you should download the data and host it yourself if used in an production environment.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Display a map on a webpage</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<link href="https://api.mapbox.com/mapbox-gl-js/v2.6.1/mapbox-gl.css" rel="stylesheet">
<script src="https://api.mapbox.com/mapbox-gl-js/v2.6.1/mapbox-gl.js"></script>
<style>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script>
mapboxgl.accessToken = 'pk.eyJ1Ijoid2l0dHJ1cCIsImEiOiJjbDc1NnFpaWIwYzZqM3VudGptdjUzNWZ1In0.R5FpTsM0CeaxLhq8i8Qmyg';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v11',
center: [-74.5, 40], // starting position [lng, lat]
zoom: 0.31741259330687854
});
map.on('load', function () {
map.addSource('cbs', { // country-boundaries-simplified
'type': 'geojson',
'data': 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_50m_admin_0_countries.geojson'
});
map.addLayer({
"id": "cf", // country-fills
"type": "fill",
"source": "cbs",
"layout": {},
"paint": {
"fill-color": "#627BC1",
"fill-opacity": 0.5
}
});
map.addLayer({
"id": "cb", // country borders
"type": "line",
"source": "cbs",
"layout": {},
"paint": {
"line-color": "#627BC1",
"line-width": 2
}
});
map.addLayer({
"id": "cfh", // country-fills-hover",
"type": "fill",
"source": "cbs",
"layout": {},
"paint": {
"fill-color": "#FFFFFF",
"fill-opacity": 1
},
"filter": ["==", "name", ""]
});
// When the user moves their mouse over the page, we look for features
// at the mouse position (e.point) and within the states layer (states-fill).
// If a feature is found, then we'll update the filter in the state-fills-hover
// layer to only show that state, thus making a hover effect.
map.on("mousemove", function(e) {
var features = map.queryRenderedFeatures(e.point, { layers: ["cf"] });
if (features.length) {
map.getCanvas().style.cursor = 'pointer';
map.setFilter("cfh", ["==", "name", features[0].properties.name]);
} else {
map.setFilter("cfh", ["==", "name", ""]);
map.getCanvas().style.cursor = '';
}
});
// Reset the state-fills-hover layer's filter when the mouse leaves the map
map.on("mouseout", function() {
map.getCanvas().style.cursor = 'auto';
map.setFilter("cfh", ["==", "name", ""]);
});
map.on("click", function(e) {
var features = map.queryRenderedFeatures(e.point, { layers: ["cf"] });
if (features.length) {
console.log(e, features[0].properties.name);
}
});
});
</script>
</body>
</html>

Clicking on a marker clicks the layer below it (Mapbox-gl)

When I click a marker on the map, the click will also be registered by the onclick listener of the trail running below the marker. How could I stop this from happening? I want the click to only be registered by the marker's onclick listener.
Code for the marker:
var el = document.createElement('div');
el.className = 'marker';
el.addEventListener('click', () => {
//functions
})
const marker = new mapboxgl.Marker(el)
.setLngLat([location.longitude, location.latitude])
.addTo(this.map);
Code for the layer:
map.addLayer({
"id": "route",
"type": "line",
"source": {
"type": "geojson",
"data": path
},
"layout": {
"line-join": "round",
"line-cap": "round"
},
"paint": {
"line-color": "#888",
"line-width": 8
}
});
Try capturing the event and stopping its propagation:
el.addEventListener('click', e => {
e.stopPropagation();
//functions
}, true);

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

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

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.

highlighting polyline features in mapbox-gl.js

I am trying to use the following code to highlight features under the mouse pointer.
The difference between my geojson data and the geojson data used in the linked example is that the example is made up of polygons whereas my geojson is made up of polylines. I have tried to modify the code accordingly in order that lines are highlighted however it does not work.
My geojson is accessible here:
http://iskandarblue.github.io/mapbox/data/prototype2.geojson
Any advice on what needs to be changed?
Example:
https://www.mapbox.com/mapbox-gl-js/example/hover-styles/
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>HTML markers from geoJSON url</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.15.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.15.0/mapbox-gl.css' rel='stylesheet'/>
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id='map'></div>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoiaXNrYW5kYXJibHVlIiwiYSI6ImNpbHIxMXA3ejAwNWl2Zmx5aXl2MzRhbG4ifQ.qsQjbbm1A71QzVg8OcR7rQ';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v8',
center: [37.625224, 55.744537,],
zoom: 13
});
map.on('style.load', function () {
map.addSource("streets", {
"type": "geojson",
"data": "http://iskandarblue.github.io/mapbox/data/prototype2.geojson"
});
map.addLayer({
"id": "m_streets",
"type": "line",
"source": "streets",
"interactive": true,
"layout": {},
"paint": {
"line-color": "#627BC1",
"line-width": 2.5
}
});
map.addLayer({
"id": "route-hover",
"type": "line",
"source": "streets",
"layout": {},
"paint": {
"line-color": "#627BC1",
"line-width": 2.5
},
"filter": ["==", "rd_name", ""]
});
// When the user moves their mouse over the page, we look for features
// at the mouse position (e.point) and within the states layer (states-fill).
// If a feature is found, then we'll update the filter in the route-hover
// layer to only show that state, thus making a hover effect.
map.on("mousemove", function(e) {
map.featuresAt(e.point, {
radius: 5,
layer: ["m_streets"]
}, function (err, features) {
if (!err && features.length) {
map.setFilter("route-hover", ["==", "rd_name", features[0].properties.rd_name]);
} else {
map.setFilter("route-hover", ["==", "rd_name", ""]);
}
});
});
});
//.addTo(map);
</script>
</body>
</html>
The route-hover layer just needs to be styled differently right? Here's a live example of your code above with a slight adjustment: https://jsbin.com/loxoquwiye/