show leaflet marker popup from outside of map dynamically - javascript

I am using Leaflet javascript library to show some earthquake information. You are able to see few red circles on map. When you click that red circle it will display few details in popup.
I want to show the popup when you click the link from outside of map. This (answer) is useful. But, I want to achieve it without ID? I mean if i have more than 30 markers on map and also I don't have any ID, just class names in my links. How do I trigger popup when I click a link from outside of map?
This (answer) is good. In this answer they mentioned marker 1, marker 2 and marker 3. But, In my case I don't know how many markers will show. Sometimes 5, 50, 100 or may be more than 150. Thats why I have asked this question.
<html>
<head>
<meta charset="utf-8" />
<title>Leaflet</title>
<link
rel="stylesheet"
href="https://unpkg.com/leaflet#1.5.1/dist/leaflet.css"
integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
crossorigin=""
/>
<script
src="https://unpkg.com/leaflet#1.5.1/dist/leaflet.js"
integrity="sha512-GffPMF3RvMeYyc1LWMHtK8EbPv0iNZ8/oTtHPx9/cc2ILxQ+u905qIwdpULaqDkyBKgOaB57QTMg7ztg8Jm2Og=="
crossorigin=""
></script>
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
</head>
<body>
<div id="map" style="width: 400px; height: 400px;"></div>
<script>
var object = {
type: "FeatureCollection",
metadata: {
generated: 1564051101000,
url:
"https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=2019-07-20&endtime=2019-07-21&minmagnitude=5",
title: "USGS Earthquakes",
status: 200,
api: "1.8.1",
count: 4
},
features: [
{
type: "Feature",
properties: {
mag: 5.2000000000000002,
place: "79km ENE of L'Esperance Rock, New Zealand",
time: 1563662132538,
updated: 1563663302040,
tz: -720,
url: "https://earthquake.usgs.gov/earthquakes/eventpage/us70004pu1",
detail: "https://earthquake.usgs.gov/fdsnws/event/1/query?eventid=us70004pu1&format=geojson",
felt: null,
cdi: null,
mmi: null,
alert: null,
status: "reviewed",
tsunami: 0,
sig: 416,
net: "us",
code: "70004pu1",
ids: ",us70004pu1,",
sources: ",us,",
types: ",geoserve,origin,phase-data,",
nst: null,
dmin: 1.9299999999999999,
rms: 1.28,
gap: 70,
magType: "mww",
type: "earthquake",
title: "M 5.2 - 79km ENE of L'Esperance Rock, New Zealand"
},
geometry: { type: "Point", coordinates: [-178.1173, -31.174800000000001, 35] },
id: "us70004pu1"
},
{
type: "Feature",
properties: {
mag: 5.5999999999999996,
place: "23km NNW of Kandrian, Papua New Guinea",
time: 1563655424914,
updated: 1563741959328,
tz: 600,
url: "https://earthquake.usgs.gov/earthquakes/eventpage/us70004psn",
detail: "https://earthquake.usgs.gov/fdsnws/event/1/query?eventid=us70004psn&format=geojson",
felt: 1,
cdi: 4.2999999999999998,
mmi: 4.4779999999999998,
alert: "green",
status: "reviewed",
tsunami: 1,
sig: 483,
net: "us",
code: "70004psn",
ids: ",us70004psn,",
sources: ",us,",
types: ",dyfi,geoserve,losspager,moment-tensor,origin,phase-data,shakemap,",
nst: null,
dmin: 3.2029999999999998,
rms: 0.89000000000000001,
gap: 28,
magType: "mww",
type: "earthquake",
title: "M 5.6 - 23km NNW of Kandrian, Papua New Guinea"
},
geometry: { type: "Point", coordinates: [149.5069, -6.0086000000000004, 59.789999999999999] },
id: "us70004psn"
},
{
type: "Feature",
properties: {
mag: 5.0999999999999996,
place: "Easter Island region",
time: 1563647034336,
updated: 1563892918040,
tz: -420,
url: "https://earthquake.usgs.gov/earthquakes/eventpage/us70004pra",
detail: "https://earthquake.usgs.gov/fdsnws/event/1/query?eventid=us70004pra&format=geojson",
felt: null,
cdi: null,
mmi: null,
alert: null,
status: "reviewed",
tsunami: 0,
sig: 400,
net: "us",
code: "70004pra",
ids: ",us70004pra,",
sources: ",us,",
types: ",geoserve,origin,phase-data,",
nst: null,
dmin: 2.7559999999999998,
rms: 0.71999999999999997,
gap: 118,
magType: "mb",
type: "earthquake",
title: "M 5.1 - Easter Island region"
},
geometry: { type: "Point", coordinates: [-111.38379999999999, -29.3232, 10] },
id: "us70004pra"
},
{
type: "Feature",
properties: {
mag: 5.0999999999999996,
place: "136km ESE of Pangai, Tonga",
time: 1563635789233,
updated: 1563636880040,
tz: -720,
url: "https://earthquake.usgs.gov/earthquakes/eventpage/us70004pp5",
detail: "https://earthquake.usgs.gov/fdsnws/event/1/query?eventid=us70004pp5&format=geojson",
felt: null,
cdi: null,
mmi: null,
alert: null,
status: "reviewed",
tsunami: 0,
sig: 400,
net: "us",
code: "70004pp5",
ids: ",us70004pp5,",
sources: ",us,",
types: ",geoserve,origin,phase-data,",
nst: null,
dmin: 3.2749999999999999,
rms: 1.3100000000000001,
gap: 116,
magType: "mww",
type: "earthquake",
title: "M 5.1 - 136km ESE of Pangai, Tonga"
},
geometry: { type: "Point", coordinates: [-173.15700000000001, -20.294899999999998, 10] },
id: "us70004pp5"
}
],
bbox: [-178.1173, -31.1748, 10, 149.5069, -6.0086, 59.79]
};
var i = 0;
document.writeln("<div>");
for (i = 0; i < object.features.length; i++) {
var timestamp = object.features[i].properties.time / 1000;
date = new Date(timestamp * 1000);
dateString = date.toUTCString();
var today = date;
today.setHours(today.getHours() + 4);
// maps
document.writeln("<div class='list'>");
document.writeln("<div>" + object.features[i].properties.mag + " Mag</div>");
document.writeln("</div>");
}
document.writeln("</div>");
var map = L.map("map").setView([-31.174800000000001, -178.1173], 2);
// load a tile layer
L.tileLayer(
"https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}",
{
attribution:
"Tiles © Esri — Source: Esri, DeLorme, NAVTEQ, USGS, Intermap, iPC, NRCAN, Esri Japan, METI, Esri China (Hong Kong), Esri (Thailand), TomTom, 2012",
maxZoom: 18
}
).addTo(map);
// load GeoJSON from an external file
$.getJSON(
"https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=2019-07-20&endtime=2019-07-21&minmagnitude=5",
function(data) {
var geojsonMarkerOptions = {
opacity: 0.8,
fillOpacity: 0.6
};
// color indication by magnitude
geoLayer = L.geoJson(data, {
// popup div content
onEachFeature: function(feature, layer) {
// variable1 = L.marker([-31.174800000000001,-178.1173]).bindPopup('The html content').addTo(map);
var popupText =
"<b>Magnitude:</b> " +
feature.properties.mag +
"<br><b>Location:</b> " +
feature.properties.place;
layer.bindPopup(popupText, {
closeButton: true,
offset: L.point(0, -20)
});
layer.on("click", function() {
layer.openPopup();
});
},
style: function(feature) {
var mag = feature.properties.mag;
if (mag >= 4.0) {
return { color: "red" };
} else if (mag >= 3.0) {
return { color: "orange" };
} else if (mag >= 2.0) {
return { color: "yellow" };
} else {
return { color: "black" };
}
},
// add GeoJSON layer to the map once the file is loaded
pointToLayer: function(feature, latlng) {
return L.circleMarker(latlng, geojsonMarkerOptions);
}
}).addTo(map);
}
);
</script>
</body>
</html>

Here is an example of a possible solution using es6:
create for instance a div which will hold the anchor tags to be added dynamically:
<div id="anchors"></div>
Now in the js file:
let markersArray = {}; // create the associative array
let magsArray = {}; // here hold the ids that correspond to the mags
// load GeoJSON from an external file
$.getJSON("https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=2019-07-20&endtime=2019-07-21&minmagnitude=5", data => {
// color indication by magnitude
L.geoJson(data, {
// add GeoJSON layer to the map once the file is loaded
pointToLayer: function(feature, latlng) {
const mag = feature.properties.mag;
const geojsonMarkerOptions = {
opacity: 0.8,
fillOpacity: 0.6,
// here define the style using ternary operators for circles
color: mag >= 4.0 ? 'red' : mag >= 3.0 ? 'orange' : mag >= 2.0 ? 'yellow' : 'black'
};
// here store the circle markers in the array
markersArray[feature.id] = L.circleMarker(latlng, geojsonMarkerOptions)
.addTo(map)
.bindPopup(
`<b>Magnitude:</b> " ${feature.properties.mag}
<br><b>Location:</b> ${feature.properties.place}`, {
closeButton: true,
offset: L.point(0, -20)
});
// here record the mags
magsArray[feature.id] = feature.properties.mag;
return L.circleMarker(latlng, geojsonMarkerOptions);
},
})
// add dynamically anchor tags
let markup = '';
for (let i in markersArray) {
markup += `<b>${magsArray[i]} Mag</b><br/>`;
}
document.getElementById('anchors').innerHTML = markup;
});
Last but not least I do not see the reason of fetching the data using the API and both have it also as a constant variable in your file.
Demo

Related

Custom Leaflet layer control

I have 7 leaflet maps created via loop and data which is exactly the same on each map controlled by a checkbox; however, my plan was to make one layer visible per map. I have searched for a solution where my maps can remain while having one layer per map, but to no avail. I had the idea of keeping one of each layer on by default when the page loads in, but I can't seem to find anything on that either. Does anyone know how to do that? I have left one layer's coordinates in the code Toe_11000 (the "11000 years ago" checkbox) since my coordinates went over the character limit but please let me know if you need clarification. If you need more of the coordinates for the layers, the full code can be found in this JSFiddle: https://jsfiddle.net/wpc6707/3ksjh06p/21/
Here's my code:
var basemapTile =
"https://stamen-tiles-{s}.a.ssl.fastly.net/terrain-background/{z}/{x}/{y}.{ext}";
var basemapOptions = {
attribution: 'Map tiles by Stamen Design, CC BY 3.0 — Map data © OpenStreetMap contributors',
subdomains: "abcd",
minZoom: 0,
maxZoom: 18,
ext: "png",
};
var glacier_map_Data = {
glacier_1: {
center: [45.5, -89.5],
zoom: 7,
description: "Glacier one",
// add title, shapes etc here
/*Glacier 11000*/
shape: (Toe_11000 = {
type: "FeatureCollection",
features: [{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [
[
[-89.01714901099996, 47.701660041000025],
[-88.98864567199996, 47.67105872900004],
[-88.89693208899996, 47.632717624000065],
[-88.76124959199996, 47.56169631900008],
[-88.58375016199994, 47.49178961600006],
[-88.44017698199997, 47.44707161100007],
[-88.30330388599998, 47.44691295700005],
[-88.17169811099996, 47.44667491700005],
[-88.02148343399995, 47.45132287700005],
[-87.87715720599994, 47.43981218000005],
[-87.74844734199996, 47.433784306000064],
[-87.64558455399998, 47.43885976400003],
[-87.53193680099997, 47.44896815100003],
[-87.38107493899997, 47.46526214000005],
[-87.24572687999995, 47.48530297000008],
[-87.13143423099996, 47.50392737300007],
[-86.98182199599995, 47.53937042800004],
[-86.82927429899996, 47.57632309400003],
[-86.62586405499997, 47.62051563700004],
[-86.53722267999996, 47.642872296000064],
[-86.52848360499996, 47.655108436000035],
[-86.66049972099995, 47.65724573000006],
[-89.01447077999995, 47.70342257000004],
[-89.01714901099996, 47.701660041000025],
],
],
},
properties: {
OBJECTID_1: 1,
OBJECTID: 1,
Years_Ago: 11000,
SHAPE_Leng: 387749.141631,
Shape_Le_1: 5.06435076694,
Shape_Area: 0.429078160361,
filename: "11000.jpg",
},
}, ],
}),
shape_style: (g11000 = L.geoJSON(Toe_11000, {
style: {
color: "#e41a1c"
},
})),
shape_listener: g11000.on({
click: function() {
$("#panel").html(
Toe_11000.features[0].properties.Years_Ago +
" Years Ago" +
info11000 +
glacierInfo +
selfPlug
);
},
}),
},
glacier_2: {
center: [45.5, -89.5],
zoom: 7,
description: "Glacier two",
// add title, shapes etc here
/*Glacier 14600*/
shape: (Toe_14600 = {
type: "FeatureCollection",
features: [{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [
[
],
],
},
properties: {
OBJECTID_1: 1,
OBJECTID: 1,
Years_Ago: 14600,
SHAPE_Leng: 2202706.20984,
Shape_Le_1: 25.0028099606,
Shape_Area: 17.1995913109,
filename: "14600.jpg",
},
}, ],
}),
shape_style: (g14600 = L.geoJSON(Toe_14600, {
style: {
color: "blue"
},
})),
shape_listener: g14600.on({
click: function() {
$("#panel").html(
Toe_14600.features[0].properties.Years_Ago +
" Years Ago" +
info14600 +
glacierInfo +
selfPlug
);
},
}),
},
glacier_3: {
center: [45.5, -89.5],
zoom: 7,
description: "Glacier three",
// add title, shapes etc here
shape: (Toe_17000 = {
type: "FeatureCollection",
features: [{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [
[
],
],
},
properties: {
OBJECTID_1: 1,
OBJECTID: 2,
Years_Ago: 17000,
SHAPE_Leng: 2261336.18634,
Shape_Le_1: 24.4337768448,
Shape_Area: 21.6098467975,
filename: "17000.jpg",
},
}, ],
}),
shape_style: (g17000 = L.geoJSON(Toe_17000, {
style: {
color: "#4daf4a"
},
})),
shape_listener: g17000.on({
click: function() {
$("#panel").html(
Toe_17000.features[0].properties.Years_Ago +
" Years Ago" +
info17000 +
glacierInfo +
selfPlug
);
},
}),
},
glacier_4: {
center: [45.5, -89.5],
zoom: 7,
description: "Glacier four",
// add title, shapes etc here
/*Glacier 20500*/
shape: (Toe_20500 = {
type: "FeatureCollection",
features: [{
type: "Feature",
geometry: {
type: "MultiPolygon",
coordinates: [
[
[
],
],
[
[
],
],
],
},
properties: {
OBJECTID_1: 1,
OBJECTID: 1,
Years_Ago: 20500,
SHAPE_Leng: 3087165.91023,
Shape_Le_1: 33.5221258781,
Shape_Area: 32.9568211425,
filename: "20500.jpg",
},
}, ],
}),
shape_style: (g20500 = L.geoJSON(Toe_20500, {
style: {
color: "#ffff33"
},
})),
shape_listener: g20500.on({
click: function() {
$("#panel").html(
Toe_20500.features[0].properties.Years_Ago +
" Years Ago" +
info20500 +
glacierInfo +
selfPlug
);
},
}),
},
glacier_5: {
center: [45.5, -89.5],
zoom: 7,
description: "Glacier five",
// add title, shapes etc here
/*Glacier 24000*/
shape: (Toe_24000 = {
type: "FeatureCollection",
features: [{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [
[
],
],
},
properties: {
OBJECTID_1: 1,
OBJECTID: 1,
Years_Ago: 24000,
SHAPE_Leng: 3034250.36063,
Shape_Le_1: 33.0014683974,
Shape_Area: 35.7394984299,
filename: "24000.jpg",
},
}, ],
}),
shape_style: (g24000 = L.geoJSON(Toe_24000, {
style: {
color: "#984ea3"
},
})),
shape_listener: g24000.on({
click: function() {
$("#panel").html(
Toe_24000.features[0].properties.Years_Ago +
" Years Ago" +
info24000 +
glacierInfo +
selfPlug
);
},
}),
},
glacier_6: {
center: [45.5, -89.5],
zoom: 7,
description: "Glacier six",
// add title, shapes etc here
/*Glacier 27500*/
shape: (Toe_27500 = {
type: "FeatureCollection",
features: [{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [
[
],
],
},
properties: {
OBJECTID_1: 1,
OBJECTID: 1,
Years_Ago: 27500,
SHAPE_Leng: 2984589.95454,
Shape_Le_1: 32.3931138132,
Shape_Area: 34.4347324387,
filename: "27500.jpg",
},
}, ],
}),
shape_style: (g27500 = L.geoJSON(Toe_27500, {
style: {
color: "#ff7f00"
},
})),
shape_listener: g27500.on({
click: function() {
$("#panel").html(
Toe_27500.features[0].properties.Years_Ago +
" Years Ago" +
info27500 +
glacierInfo +
selfPlug
);
},
}),
},
glacier_7: {
center: [45.5, -89.5],
zoom: 7,
description: "Glacier seven",
// add title, shapes etc here
shape: (Toe_31500 = {
type: "FeatureCollection",
features: [{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [
[
],
],
},
properties: {
OBJECTID_1: 1,
OBJECTID: 2,
Years_Ago: 31500,
SHAPE_Leng: 1478866.18087,
Shape_Le_1: 15.9994195189,
Shape_Area: 9.83976333148,
filename: "31500.jpg",
},
}, ],
}),
shape_style: (g31500 = L.geoJSON(Toe_31500, {
style: {
color: "#a65628"
},
})),
shape_listener: g31500.on({
click: function() {
$("#panel").html(
Toe_31500.features[0].properties.Years_Ago +
" Years Ago" +
info31500 +
glacierInfo +
selfPlug
);
},
}),
},
};
var initMap = (EL) => {
var id = EL.dataset.map; // returns i.e: "glacier_1"
var data = glacier_map_Data[id];
var map = L.map(EL).setView(data.center, data.zoom);
L.tileLayer(basemapTile, basemapOptions).addTo(map);
var glacierLayers = L.control
.layers(null, {
//formatting from iH8 answer on StackOverflow https://stackoverflow.com/a/46044847/16538252
"31500 years ago": g31500,
"27500 years ago": g27500,
"24000 years ago": g24000,
"20500 years ago": g20500,
"17000 years ago": g17000,
"14600 years ago": g14600,
"11000 years ago": g11000,
})
.addTo(map);
};
var ELS_map = document.querySelectorAll("[data-map]");
ELS_map.forEach(initMap);
/*Stylesheet by Will P. Campbell,2021*/
body {
background-color: #ececec;
}
/* idea from Roko C Buljian answer on StackOverflow: https://stackoverflow.com/q/68836662/16538252 */
[data-map] {
height: 650px;
width: 60%;
border: 5px solid black;
margin: 20px;
}
h1 {
font-family: "Franklin Gothic Medium", "Arial Narrow", Arial, sans-serif;
}
#panel {
position: relative;
right: 0;
border: 5px outset black;
background-color: lightblue;
text-align: center;
width: 25%;
height: auto;
padding: 20px;
display: inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin="" />
<script src="https://unpkg.com/leaflet#1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>WISCONSIN GLACIER TIME LAPSE</title>
</head>
<body>
<h1>WISCONSIN GLACIER TIME LAPSE</h1>
<!-- map data divs -->
<div data-map="glacier_1"></div>
<div data-map="glacier_2"></div>
<div data-map="glacier_3"></div>
<div data-map="glacier_4"></div>
<div data-map="glacier_5"></div>
<div data-map="glacier_6"></div>
<div data-map="glacier_7"></div>
<!--idea from Roko C Buljian answer on StackOverflow: https://stackoverflow.com/q/68836662/16538252-->
<div id="panel"><b>Glacier Information Panel</b><br>
<p>Use the checkbox and click on each glacier to learn more about them!</p>
</div>
</body>
</html>
You were on the right direction!
So, if you use all your data inside glacier_map_Data, where the properties reflect the data-* attribute of each element in the Document i.e: <div data-map="glacier_1"></div> add inside it also the properties label, shape and style :
Here's the "new" data example for every glacier_(N)
// glacier_* :
{
center: [45.5, -89.5],
zoom: 7,
label: "11000 years ago",
description: "Glacier one description info goes here...",
shape: {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [[/* .... */],],
},
properties: { /* .... */ },
},
],
},
style: {
color: "#e41a1c",
}
},
having that kind of data, you first need to:
Create all the LeafLet layers
Create all the LeafLet layers inside a separate Object. You'll later add that object to every map:
// Create the L.geoJSON LAYERS to be later added to each map!
const overlays = Object.entries(glacier_map_Data).reduce((acc_obj, [key, data]) => {
// Define the geoJSON layer instance
const L_geoLSON = L.geoJSON(data.shape, {style: data.style});
// Add click listener to layer
L_geoLSON.on({
click() {
EL_panel.innerHTML = `<h2>${data.title}</h2><p>${data.description}</p>`;
}
});
// Create the return Object:
acc_obj[key] = {
label: data.title,
L_geoJSON
};
// Return the accumulator (see: MDN: Array.prototype.reduce() for more info)
return acc_obj;
}, {});
the above will generate something similar as what you used in your code for var glacierLayers but - with a slight difference:
// overlays =
{
glacier_1 : {
label: "11000 years ago",
L_geoJSON: {} // the LeafLet geoJSON instance
},
// glacier 2, 3 etc...
}
having that custom object in place now, all you need is to: when looping your Maps convert it to the format expected by LeafLet {"layer description 1": geoJSON, /* etc */}
Add multiple layers to LeafLet map and make respective one active:
while looping your Maps ELements, you get the current element's data-* attribute const id = EL.dataset.map ID - that ID can be now referenced to get the active layer too:
// Maps initializator
// Applays LeafLet to each map Element `EL`
const initMap = (EL) => {
const id = EL.dataset.map; // gives back i.e: "glacier_1" 2, 3 etc...
const data = glacier_map_Data[id];
// Assign a LeafLet Map instance to a specific DOM element and set its view
const L_map = L.map(EL).setView(data.center, data.zoom);
L.tileLayer(L_basemapTile, L_basemapOptions).addTo(L_map);
// Convert the
const overlayMaps = Object.values(overlays).reduce((acc_obj, data) => {
acc_obj[data.label] = data.L_geoLSON
return acc_obj;
}, {});
// Add control layers to map:
L.control.layers(null, overlayMaps).addTo(L_map);
// Make specific one "Active" (checked!) and visible on map:
L_map.addLayer(overlays[id].L_geoJSON);
};
That's basically it. See in the below example how the click handlers are resolved to make it all work:
const EL_panel = document.querySelector("#panel");
const L_basemapTile = "https://stamen-tiles-{s}.a.ssl.fastly.net/terrain-background/{z}/{x}/{y}.{ext}";
const L_basemapOptions = {
attribution: 'Map tiles by Stamen Design, CC BY 3.0 — Map data © OpenStreetMap contributors',
minZoom: 0,
maxZoom: 18,
ext: "png",
};
const glacier_map_Data = {
glacier_1: {
center: [45.5, -89.5],
zoom: 7,
label: "11000 years ago",
description: "Glacier one description goes here...",
shape: {
type: "FeatureCollection",
features: [{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [
[
[-89.01714901099996, 47.701660041000025],
[-88.98864567199996, 47.67105872900004],
[-88.89693208899996, 47.632717624000065],
[-88.76124959199996, 47.56169631900008],
[-88.58375016199994, 47.49178961600006],
[-88.44017698199997, 47.44707161100007],
[-88.30330388599998, 47.44691295700005],
[-88.17169811099996, 47.44667491700005],
[-88.02148343399995, 47.45132287700005],
[-87.87715720599994, 47.43981218000005],
[-87.74844734199996, 47.433784306000064],
[-87.64558455399998, 47.43885976400003],
[-87.53193680099997, 47.44896815100003],
[-87.38107493899997, 47.46526214000005],
[-87.24572687999995, 47.48530297000008],
[-87.13143423099996, 47.50392737300007],
[-86.98182199599995, 47.53937042800004],
[-86.82927429899996, 47.57632309400003],
[-86.62586405499997, 47.62051563700004],
[-86.53722267999996, 47.642872296000064],
[-86.52848360499996, 47.655108436000035],
[-86.66049972099995, 47.65724573000006],
[-89.01447077999995, 47.70342257000004],
[-89.01714901099996, 47.701660041000025],
],
],
},
properties: {
OBJECTID_1: 1,
OBJECTID: 1,
Years_Ago: 11000,
SHAPE_Leng: 387749.141631,
Shape_Le_1: 5.06435076694,
Shape_Area: 0.429078160361,
filename: "11000.jpg",
},
}, ],
},
style: {
color: "#e41a1c",
}
},
glacier_2: {
center: [45.5, -89.5],
zoom: 7,
label: "14600 years ago",
description: "Glacier two description goes here...",
shape: {
type: "FeatureCollection",
features: [{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [
[
[-90.65116417499996, 47.70293454200004],
[-90.72482365299999, 47.673924999000064],
[-90.79822703099995, 47.63344243800003],
[-90.87151684099996, 47.592913355000064],
[-90.93607653299995, 47.54240954900007],
[-90.98389479799994, 47.50486972300007],
[-91.01266156999998, 47.46605101600005],
[-91.03524057399994, 47.43585163000006],
[-91.09569047499997, 47.40672034700003],
[-91.16068607799997, 47.39608128700007],
[-91.20242634199997, 47.38136616700007],
[-91.24370674999994, 47.34807033200008],
[-91.24727017899994, 47.32089010200008],
[-91.27829107399998, 47.30054916700004],
[-91.35252049299999, 47.24684182500005],
[-91.42454322999998, 47.19454164700005],
[-91.49851758599999, 47.142169952000074],
[-91.58297018999997, 47.09531966900005],
[-91.69593298799998, 47.02941600500003],
[-91.78970295499994, 46.95941544900006],
[-91.82835428899995, 46.930232197000066],
[-91.91162510599997, 46.86744039100006],
[-91.99554737199998, 46.82743409100004],
[-92.06911560299994, 46.79183942000003],
[-92.12271105199994, 46.779428163000034],
[-92.18228311199994, 46.76116312500005],
[-92.25397574199997, 46.73548525600006],
[-92.32346255299996, 46.70837829200008],
[-92.37452539699996, 46.68875637000008],
[-92.41380912499994, 46.68507654200005],
[-92.47155654999995, 46.67669948400004],
[-92.49779041299996, 46.66041357700004],
[-92.53630909799995, 46.640992280000034],
[-92.60352557599998, 46.61519304900003],
[-92.65025475699997, 46.595545755000046],
[-92.66997578199994, 46.57508444400003],
[-92.69410222099998, 46.56023089900003],
[-92.73425967299994, 46.53498854400004],
[-92.79268852199999, 46.503571829000066],
[-92.84256524699998, 46.468051606000074],
[-92.88183268599994, 46.42849094400003],
[-92.92753540999996, 46.394466917000045],
[-92.94989701799994, 46.34959887800005],
[-92.95186608799997, 46.30954130100008],
[-92.92975250899997, 46.28153421700006],
[-92.85925850399997, 46.27331860700008],
[-92.79127616799997, 46.27357100900008],
[-92.71321257399995, 46.27830917600005],
[-92.63952461199995, 46.28860811000004],
[-92.57829646799996, 46.301436514000045],
[-92.50925582199994, 46.32440533500005],
[-92.44221727099995, 46.347289440000054],
[-92.41261793199999, 46.37792243000007],
[-92.37035638299994, 46.40309578500006],
[-92.32010085699994, 46.43555965100006],
[-92.22421472899998, 46.46604055800003],
[-92.16676037899998, 46.47714513900007],
[-92.07164040799995, 46.47747958900004],
[-91.96355058399996, 46.462242262000075],
[-91.88129117799997, 46.47505522800003],
[-91.84860834599993, 46.487018110000065],
[-91.75759648199994, 46.48702458100007],
[-91.67480884399998, 46.485409692000076],
[-91.61092690599997, 46.49347106100004],
[-91.53298945499995, 46.517401738000046],
[-91.46184380399995, 46.56548027200006],
[-91.39439978099995, 46.60108704600003],
[-91.31293960199997, 46.66110276500007],
[-91.18166198599994, 46.731109263000064],
[-91.12163612599994, 46.77552488500004],
[-91.02482937399998, 46.78786178000007],
[-90.98063779999995, 46.797773128000074],
[-90.96927097899999, 46.782631328000036],
[-90.95760682899999, 46.75034730400006],
[-91.00666688699994, 46.706114670000034],
[-91.04472870499995, 46.66958103600007],
[-91.09664029099997, 46.636712301000045],
[-91.13687825499994, 46.57726777900007],
[-91.18839689999999, 46.532931133000034],
[-91.22591702999995, 46.48300696300004],
[-91.22480609399997, 46.433490293000034],
[-91.18738430599996, 46.359591409000075],
[-91.12616009499999, 46.325921202000075],
[-90.99618142799994, 46.285217860000046],
[-90.89141040599998, 46.26322281700004],
[-90.77320977799997, 46.256463342000075],
[-90.59165834999999, 46.22897204100008],
[-90.47359851299996, 46.22571206300006],
[-90.21011180299996, 46.22840493600006],
[-90.07834092799999, 46.21714115300006],
[-89.99052527699996, 46.20002253800004],
[-89.63663278999996, 46.19754044900003],
[-89.30472963899996, 46.19409865700004],
[-89.14564109599996, 46.193020372000035],
[-89.10690236799996, 46.21367948200003],
[-88.97509624199995, 46.21828879600008],
[-88.74396655199996, 46.24455812300005],
[-88.43920812199997, 46.263282384000036],
[-88.18463496799995, 46.27857294900008],
[-88.00977466999996, 46.175646776000065],
[-87.99389010599998, 46.04677587200007],
[-88.03142757799998, 45.90454467200004],
[-88.07824403599994, 45.733876871000064],
[-88.11693049199994, 45.64521481500003],
[-88.15630836499997, 45.53154329200004],
[-88.25459067099996, 45.31159869500004],
[-88.32963412999999, 45.169820886000025],
[-88.40834291299996, 45.06376788400007],
[-88.48581727299995, 44.99336901300006],
[-88.79481685399998, 44.90415892300007],
[-88.88639060299994, 44.84792515000004],
[-88.88261184299995, 44.78357859500005],
[-88.94319230899998, 44.76271860500003],
[-88.97231671099996, 44.62840776200005],
[-89.00318747399996, 44.57866096200007],
[-89.02004076199995, 44.46804576400007],
[-89.04649611099995, 44.37537170000007],
[-89.10740785599995, 44.30082986600007],
[-89.08883401599996, 44.21492877800006],
[-89.02088686299999, 44.117891385000064],
[-88.83475711099999, 43.998228366000035],
[-88.68786675299998, 43.92517043600003],
[-88.62533997199995, 43.84939582800007],
[-88.57299960499995, 43.76656712400006],
[-88.46045322499998, 43.73294585800005],
[-88.39507582999994, 43.78207346700003],
[-88.33422715399996, 43.841949181000075],
[-88.26389529699998, 43.883781630000044],
[-88.26171217099994, 43.95878690500007],
[-88.25436012199998, 44.04085874400005],
[-88.13665456199999, 44.003267237000045],
[-88.04759712699996, 44.00177966800004],
[-87.97724235799996, 44.03271403600007],
[-87.91264601899996, 44.03869804900006],
[-87.85100620199995, 43.96251794800003],
[-87.84031258699997, 43.84797273600003],
[-87.77934997599993, 43.76104507100007],
[-87.69970123099995, 43.65226923900008],
[-87.59451333699997, 43.57506238600007],
[-87.41895871099996, 43.54264457600004],
[-87.19847646199997, 43.53030423300004],
[-87.05535483399996, 43.54457143500008],
[-86.90199607799997, 43.56552812900003],
[-86.73246550099998, 43.61082922300005],
[-86.59688342599998, 43.66046715300007],
[-86.47311237099996, 43.75675903800004],
[-86.41494068499998, 43.905016706000026],
[-86.38487126299998, 43.99339418100004],
[-86.33611529199999, 44.14190469500005],
[-86.23094835399996, 44.23494796600005],
[-86.07578505799995, 44.32618325100003],
[-85.99546925899995, 44.409139733000075],
[-85.93780993299998, 44.44997420000004],
[-85.94529025199995, 44.48596854700003],
[-85.88575853799995, 44.551719080000055],
[-85.82903334099996, 44.64612264200008],
[-85.67299230199995, 44.65817042300006],
[-85.49721378799995, 44.66565292100006],
[-85.37988257999996, 44.69311130300008],
[-85.26070073999995, 44.74180747400004],
[-85.20102381099997, 44.79647274300004],
[-85.12731019099994, 44.896951657000045],
[-85.07522771199996, 44.976883351000026],
[-84.82164997499996, 47.579520486000035],
[-90.67336377599997, 47.71242423500007],
[-90.65116417499996, 47.70293454200004],
],
],
},
properties: {
OBJECTID_1: 1,
OBJECTID: 1,
Years_Ago: 14600,
SHAPE_Leng: 2202706.20984,
Shape_Le_1: 25.0028099606,
Shape_Area: 17.1995913109,
filename: "14600.jpg",
},
}, ],
},
style: {
color: "blue",
}
},
glacier_3: {
center: [45.5, -89.5],
zoom: 7,
label: "17000 years ago",
description: "Glacier three description goes here...",
shape: {
type: "FeatureCollection",
features: [{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [
[
[-90.80257177799996, 47.694422805000045],
[-90.86222397199998, 47.665247442000066],
[-90.91508604399996, 47.62484245700006],
[-90.95803303899999, 47.58544825300004],
[-91.01917862199997, 47.54492503300003],
[-91.09271780999995, 47.49663293300006],
[-91.13744776499999, 47.48572257300003],
[-91.19432270499999, 47.453717991000076],
[-91.22598803099999, 47.42671888800004],
[-91.25327888599998, 47.39404483100003],
[-91.29858830799998, 47.35449497500008],
[-91.35488375299997, 47.30908341500003],
[-91.41382942899997, 47.261706307000054],
[-91.49191066199995, 47.20262235200005],
[-91.56326114699999, 47.15786191900003],
[-91.61665197199994, 47.12283520300008],
[-91.64494317099997, 47.09005134100005],
[-91.68031442299997, 47.061918510000055],
[-91.73452409299995, 47.01444274000005],
[-91.74858348099997, 46.94175084200003],
[-91.73854830599998, 46.900235628000075],
[-91.72864410799997, 46.86228889100005],
[-91.70514887199994, 46.83287815500006],
[-91.66600897199999, 46.80131027900006],
[-91.62366569299996, 46.776917671000035],
[-91.55026225899996, 46.75531549600004],
[-91.46858503999994, 46.74567813800007],
[-91.38377803899994, 46.747925758000065],
[-91.24871820299995, 46.74947940000004],
[-91.19708552899993, 46.76431757600005],
[-91.14894001899995, 46.781478469000035],
[-91.08834267399999, 46.78445186300007],
[-91.00692035499998, 46.786387758000046],
[-90.97908530999996, 46.78067668300008],
[-90.94737340199998, 46.75118052900007],
[-90.93838366699998, 46.73220616100008],
[-90.94831208099998, 46.70593260000004],
[-90.95989734799997, 46.67607254100005],
[-91.00120538799996, 46.66500363200004],
[-91.02850889499996, 46.64571269000004],
[-91.05754397599998, 46.62758970900006],
[-91.07281220699997, 46.61316088700005],
[-91.09452456799994, 46.57604782900006],
[-91.11295233699997, 46.54848696500005],
[-91.11776169199999, 46.53058148500003],
[-91.12399765899994, 46.498374786000056],
[-91.12685495599999, 46.46977266600004],
[-91.11093806599996, 46.449688397000045],
[-91.08423164199996, 46.405892745000074],
[-91.04970107799994, 46.400261948000036],
[-91.00833934399998, 46.39706236200004],
[-90.95158052599999, 46.39873937200008],
[-90.91358681599996, 46.39071504300006],
[-90.87046244599998, 46.383907855000075],
[-90.81185063999999, 46.37600480700007],
[-90.76383959199995, 46.38705097700006],
[-90.72438110399997, 46.39564190900006],
[-90.63847221899994, 46.40686916000004],
[-90.56462655999997, 46.42273526000008],
[-90.51134690599997, 46.432510584000056],
[-90.45289127799998, 46.44347225900003],
[-90.32730869399995, 46.46771218100008],
[-90.26707800199995, 46.483346151000035],
[-90.14297639499995, 46.48118746100005],
[-89.84300789599996, 46.47969872700003],
[-89.65732711399994, 46.40785826900003],
[-89.46590880699995, 46.26901435500008],
[-89.38473015499994, 46.15906824800004],
[-89.37232217399998, 46.044697961000054],
[-89.29895872499998, 45.89662691800004],
[-89.19127953899994, 45.795896034000066],
[-89.04288713099999, 45.713779739000074],
[-88.81317766399997, 45.64494244800005],
[-88.52326877299998, 45.56535339100003],
[-88.34772919599999, 45.53913320500004],
[-88.28172005799996, 45.481001443000025],
[-88.24935543399994, 45.432878068000036],
[-88.29265439599999, 45.34303229100004],
[-88.51505546999994, 45.10321006100003],
[-88.68092601499995, 44.90994226600003],
[-88.83212689599998, 44.72580551000004],
[-88.88282864799999, 44.521468026000036],
[-88.93928291699996, 44.345738820000065],
[-88.91597518599997, 44.16924722700003],
[-88.90511613299998, 44.04050887900007],
[-88.77686594499994, 43.85339730000004],
[-88.63498640399996, 43.723149343000046],
[-88.45317832499995, 43.63983570600004],
[-88.30836892799994, 43.656842280000035],
[-88.18115130199999, 43.74064944300005],
[-88.10533528899998, 43.64412736300005],
[-88.07694916099996, 43.50548020300005],
[-88.01697621299996, 43.33769126900006],
[-88.02053189599997, 43.22816265400007],
[-87.97488779599996, 43.032002686000055],
[-87.92574681699995, 42.754748824000046],
[-87.89018209199998, 42.46818362000005],
[-87.89013807499998, 42.277565752000044],
[-87.84692496099996, 42.03848385400005],
[-87.74604783999996, 41.817324159000066],
[-87.58802798299996, 41.613950112000055],
[-87.35004156799994, 41.532454906000055],
[-87.03022367399996, 41.59135333200004],
[-86.77141863699995, 41.68921014000006],
[-86.51666584599997, 41.81518954100005],
[-86.41223131899994, 41.97398477400003],
[-86.29809079699999, 42.180014037000035],
[-86.12804763999998, 42.445983640000065],
[-86.00558320699997, 42.65141657300006],
[-85.85659114999999, 43.04632439000005],
[-85.84500492099994, 43.21741730100007],
[-86.03504616299995, 43.40045063700006],
[-85.91772016199997, 43.686927799000046],
[-85.72568643499994, 43.89427499900006],
[-85.70752393799995, 44.146079014000065],
[-85.57577670099994, 44.226791743000035],
[-85.33539704999998, 44.25055543500008],
[-85.15006930999994, 44.24758344700007],
[-84.83610884999996, 47.577689332000034],
[-90.81976554599999, 47.700655631000075],
[-90.80257177799996, 47.694422805000045],
],
],
},
properties: {
OBJECTID_1: 1,
OBJECTID: 2,
Years_Ago: 17000,
SHAPE_Leng: 2261336.18634,
Shape_Le_1: 24.4337768448,
Shape_Area: 21.6098467975,
filename: "17000.jpg",
},
}, ],
},
style: {
color: "#4daf4a",
}
}
};
// Create the L.geoJSON LAYERS to be later added to each map!
const overlays = Object.entries(glacier_map_Data).reduce((acc_obj, [key, data]) => {
// Define the geoJSON layer instance
const L_geoJSON = L.geoJSON(data.shape, {
style: data.style
});
// Add click listener to layer
L_geoJSON.on({
click() {
EL_panel.innerHTML = `<h2>${data.label}</h2><p>${data.description}</p>`;
}
});
// Create the return Object:
acc_obj[key] = {
label: data.label,
L_geoJSON
};
// Return the accumulator (see: MDN: Array.prototype.reduce() for more info)
return acc_obj;
}, {});
// console.log(overlays); // See it to understand it!
// Maps initializator
// Applays LeafLet to each map Element `EL`
const initMap = (EL) => {
const id = EL.dataset.map; // gives back i.e: "glacier_1" 2, 3 etc...
const data = glacier_map_Data[id];
// Assign a LeafLet Map instance to a specific DOM element and set its view
const L_map = L.map(EL).setView(data.center, data.zoom);
L.tileLayer(L_basemapTile, L_basemapOptions).addTo(L_map);
// Convert the
const overlayMaps = Object.values(overlays).reduce((acc_obj, data) => {
acc_obj[data.label] = data.L_geoJSON
return acc_obj;
}, {});
// Add control layers to map:
L.control.layers(null, overlayMaps).addTo(L_map);
// Make specific one "Active" (checked!) and visible on map:
L_map.addLayer(overlays[id].L_geoJSON);
};
// Loop map elements in DOM and assign
var ELS_map = document.querySelectorAll("[data-map]");
ELS_map.forEach(initMap);
/*Stylesheet by Will P. Campbell,2021*/
body {
background-color: #ececec;
}
[data-map] {
height: 650px;
width: 60%;
border: 5px solid black;
margin: 20px;
}
h1 {
font-family: "Franklin Gothic Medium", "Arial Narrow", Arial, sans-serif;
}
#panel {
position: fixed;
right: 0;
top: 0;
border: 5px outset black;
background-color: lightblue;
text-align: center;
width: 25%;
height: auto;
padding: 20px;
}
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin="" />
<h1>WISCONSIN GLACIER TIME LAPSE</h1>
<!-- map data divs -->
<div data-map="glacier_1"></div>
<div data-map="glacier_2"></div>
<div data-map="glacier_3"></div>
<div id="panel"><b>Glacier Information Panel</b><br>
<p>Use the checkbox and click on each glacier to learn more about them!</p>
</div>
<script src="https://unpkg.com/leaflet#1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
<script type="text/javascript" src="js/main.js"></script>

mapbox geojson description for popup showing 'undefined'

I have the following code but when I click on a point to open a popup it returns 'undefined' and I cannot seem to work out why.
I'm pulling the description field from the geoJSON external source which I have control over but for some reason it just does not want to populate the description HTML in my array. I took the example for the popup from the mapbox website so I know it works there. I have checked, rechecked and triple checked but I think I cannot see the tree for the forest lol.
Could someone maybe help me please? thanks.
<script>
// ajax loading gif
$(document).ready(function () {
setTimeout(function () {
$("#ajax-loader").removeClass("is-active");
}, 6000);
});
// vars
var initialOpacity = 0.2;
var opacity = initialOpacity;
// mapbox api
mapboxgl.accessToken = "hidden_api_key";
var map = new mapboxgl.Map({
container: "map", // container ID
style: "mapbox://styles/mapbox/dark-v10",
center: [-2.582861, 53.5154517],
zoom: 5,
maxZoom: 16,
minZoom: 0,
});
map.on("load", function () {
// get hotspot locations
map.addSource("hotspot_locations", {
type: "geojson",
data: "https://netmaker.io/dashboard/public_actions.php?a=ajax_helium_miners_location",
cluster: false,
clusterMaxZoom: 10, // max zoom to cluster points on
clusterRadius: 50, // radius of each cluster when clustering points (defaults to 50)
});
// add 300m circle around each hotspot
map.addLayer({
id: "circle500",
type: "circle",
source: "hotspot_locations",
paint: {
"circle-radius": {
stops: [
[0, 1],
[16, 600],
],
base: 2,
},
"circle-color": "green",
"circle-opacity": 0.1,
"circle-stroke-width": 0,
"circle-stroke-color": "white",
},
});
// add hotspot location
map.addLayer({
id: "hotspots-layer",
type: "circle",
source: "hotspot_locations",
paint: {
"circle-radius": 2,
"circle-stroke-width": 2,
// "circle-color": "#36d293",
"circle-color": "white",
"circle-stroke-color": [
"match",
["get", "status"],
"online",
"#36d293",
"offline",
"#d23636",
"orange", // other
],
// "circle-stroke-color": '#36d293',
},
});
});
// ajax call hotspots location by name
var customData;
$.ajax({
async: false,
type: "GET",
global: false,
dataType: "json",
url: "https://netmaker.io/dashboard/public_actions.php?a=ajax_helium_miners_location_customdata",
success: function (data) {
customData = data;
},
});
// custom data using hotspot name
function forwardGeocoder(query) {
var matchingFeatures = [];
for (var i = 0; i < customData.features.length; i++) {
var feature = customData.features[i];
if (feature.properties.title.toLowerCase().search(query.toLowerCase()) !== -1) {
// feature["place_name"] = '<img src="https://netmaker.io/dashboard/images/helium_logo.svg" alt="" width="15px"> ' + feature.properties.title;
feature["place_name"] = feature.properties.title;
feature["center"] = feature.geometry.coordinates;
feature["place_type"] = ["hotspot"];
matchingFeatures.push(feature);
}
}
return matchingFeatures;
}
// add the control to the map.
map.addControl(
new MapboxGeocoder({
accessToken: mapboxgl.accessToken,
localGeocoder: forwardGeocoder,
zoom: 14,
placeholder: "Search: address or hotspot name",
mapboxgl: mapboxgl,
})
);
map.on("click", "hotspots-layer", function (e) {
var coordinates = e.features[0].geometry.coordinates.slice();
var description = e.features[0].properties.description;
while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
}
new mapboxgl.Popup().setLngLat(coordinates).setHTML(description).addTo(map);
});
map.on("mouseenter", "hotspots-layer", function () {
map.getCanvas().style.cursor = "pointer";
});
map.on("mouseleave", "hotspots-layer", function () {
map.getCanvas().style.cursor = "";
});
</script>
You're recieving an undefined because e.features[0].properties.description doesn't exist in the "hotspots-layer" data.
"features": [
{
"type": "Feature",
"properties": {
"status": "online"
},
"geometry": {
"type": "Point",
"coordinates": [
"119.73479929772",
"30.240836896893",
0
]
}
},
The only "description" in this case that you can return is the e.features[0].properties.status as seen here:
map.on("click", "hotspots-layer", function (e) {
var coordinates = e.features[0].geometry.coordinates.slice();
var description = e.features[0].properties.status;
while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
}
console.log(description)
new mapboxgl.Popup().setLngLat(coordinates).setHTML(description).addTo(map);
});
This code snippet will allow the click event to show you the status when you interact with the hotspot location.

Mapbox - Trying to add a route between several markers

I am trying to learn JS and creating maps with the Mapbox GL JS and Directions. I managed to add markers to a map, and now I would like to add a route between the markers (1 -> 2 -> 3 -> 4).
After playing around for several time now, I got stuck. The markers are added, but no route is shown.
Would be create if you could help me :)
Thanks, Ben
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title></title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.11.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.11.0/mapbox-gl.css' rel='stylesheet' />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
.marker {
background-image: url('mapbox-icon.png');
background-size: cover;
width: 50px;
height: 50px;
border-radius: 50%;
cursor: pointer;
}
</style>
</head>
<body>
<div id='map'></div>
<script>
mapboxgl.accessToken = 'xxx';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v10',
center: [-122.662323, 45.523751],
zoom: 11
});
// code from the next step will go here!
var geojson = {
type: 'FeatureCollection',
features: [{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [-122.662323, 45.523751]
},
properties: {
title: 'Mapbox',
description: 'Washington, D.C.'
}
},
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [-122.692323, 45.523751]
},
properties: {
title: 'Mapbox',
description: 'San Francisco, California'
}
},
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [-122.612323, 45.523751]
},
properties: {
title: 'Mapbox',
description: 'San Francisco, California'
}
},
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [-122.682323, 45.523751]
},
properties: {
title: 'Mapbox',
description: 'San Francisco, California'
}
}]
};
// add markers to map
geojson.features.forEach(function(marker) {
// create a HTML element for each feature
var el = document.createElement('div');
el.className = 'marker';
// make a marker for each feature and add to the map
new mapboxgl.Marker(el)
.setLngLat(marker.geometry.coordinates)
.addTo(map);
});
map.on('load', () => {
for (i = 0; i < geojson.length; i++) {
for(j = i+1; j < geojson.length; j++) {
var geomFrom = geojson[i];
var geomTo = geojson[j];
$.get(`https://api.mapbox.com/directions/v5/mapbox/driving/` + geomFrom[0] + ',' + geoFrom[1] + ';' + geomTo[0] + ',' + geomTo[1] + `?access_token=${mapboxgl.accessToken}&geometries=geojson`, data => {
map.addLayer({
id: 'route',
type: 'line',
source: {
type: 'geojson',
data: {
type: 'Feature',
properties: {},
geometry: data.routes[0].geometry,
},
},
layout: {
'line-join': 'round',
'line-cap': 'round',
},
paint: {
'line-color': '#ff7e5f',
'line-width': 8,
},
})
})
};
};
});
</script>
</body>
</html>
There are many issues I have found in the code, but long story short, the source you are creating is wrongly created. To simplify the explanation I had to remove the double for loop and the call to the service to show you how you should create the source for the path.
I have shaped this fiddle creating a path in Portland.
Here is the relevant js code for the layer you have to create:
map.addLayer({
id: 'route',
type: 'line',
source: {
'type': 'geojson',
'data': {
'type': 'Feature',
'properties': {},
'geometry': {
'type': 'LineString',
'coordinates': [
[
-122.68035572839027,
45.52729517240144
],
[
-122.67657260381876,
45.527330174436116
],
[
-122.67657129671815,
45.52666556739695
],
[
-122.67085005715236,
45.52677044480427
],
[
-122.66645605237485,
45.52862702776275
],
[
-122.66560830926798,
45.52866212597536
],
[
-122.66532421497476,
45.52712020010674
],
[
-122.6654770006126,
45.52158881104725
],
[
-122.66684678096325,
45.51749007039993
]
],
},
}
},
layout: {
'line-join': 'round',
'line-cap': 'round'
},
paint: {
'line-color': '#888',
'line-width': 8
}
})
Now knowing how this layer needs to be created, you can surely bring back your loops and the call to the service, but as long you are double looping you'll be creating a layer per loop, which is definitely NOT desirable nor recommendable.
I also noted the coords of the your geojson source are repeated and the coords do not correspond to the places indicated, but I ignored them for the sample in the fiddle.
If this answer solves your question about how to add a route between several markers, please mark it as answer accepted, in this way it will also help other users to know it was the right solution

Need help on adding popup leaflet

This is my json response from URL:
{
"geometry": {
"type": "Point",
"coordinates": [
-1.480921,
52.979698
],
"Timestamp": "2017-07-09T09:21:30",
"GatewayID": 193,
"Speed": 94.9,
"Heading": 157
},
"type": "Feature",
"properties": {}
}
This is my js file:
var map = L.map('map', {
'center': [0, 0],
'zoom': 0,
'layers': [
L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {
'attribution': 'Map data © OpenStreetMap contributors'
})
]
});
var geojsonMarkerOptions = {
radius: 18,
fillColor: "#ff7800",
color: "#000",
weight: 1,
opacity: 1,
fillOpacity: 0.8
};
var realtime = L.realtime({
url: 'http://127.0.0.1:8000/mongo/getgpsdata/',
crossOrigin: true,
type: 'json'
}, {
interval: 3 * 1000,
pointToLayer: function (feature, latlng) {
return L.circleMarker(latlng)
}
}).addTo(map);
realtime.on('layeradd', function(e) {
var coordPart = function(v, dirs) {
return dirs.charAt(v >= 0 ? 0 : 1) +
(Math.round(Math.abs(v) * 100) / 100).toString();
},
popupContent = function(fId) {
var feature = e.features[fId],
c1 = feature.geometry.Speed
c2=feature.geometry.Timestamp
c = feature.geometry.coordinates;
return '<b>coord: </b>' +c + '<br><b>Speed:</b> '+c1 + '<br><b>Time: </b>' + c2;
},
bindFeaturePopup = function(fId) {
realtime.getLayer(fId).bindPopup(popupContent(fId));
},
updateFeaturePopup = function(fId) {
realtime.getLayer(fId).getPopup().setContent(popupContent(fId));
};
map.fitBounds(realtime.getBounds(), {maxZoom: 30});
Object.keys(e.enter).forEach(bindFeaturePopup);
Object.keys(e.update).forEach(updateFeaturePopup);
});
It works perfectly fine but it wont show the popups, but if i give 'update' in place of 'layeradd' then it gives me the popups but the historical data is lost as it gets updated every time.
Any help would be great, Thanks!
Add bindPopup while returning the Marker, this worked for me.
return L.circleMarker(latlng).bindPopup("your content")

Ammaps - My own images need to be added in particular latitude and longitude

I have been given the following requirement.
Need to plot weather for particular main cities in Canada
I am able to get the current weather details from an API in internet through (web handler and query strings.)
Hence, I have the latitude and longitude details handy along with the the weather condition(Cloudy , sunny,Rainy etc)
I just need to show clouds on city where it is cloudy , Rainy image on city where it's raining etc
This has to be done in Javascript AMmaps .
My complete code is pasted below.I don't find a way to push my own images to the Map
AmCharts.ready(function () {
map = new AmCharts.AmMap();
map.pathToImages = "http://www.amcharts.com/lib/3/images/";
map.panEventsEnabled = true;
map.backgroundColor = "#666666";
map.backgroundAlpha = 1;
colorSteps: 1,
map.zoomControl.panControlEnabled = true;
map.zoomControl.zoomControlEnabled = true;
var dataProvider = {
map: "canadaLow",
getAreasFromMap: true,
areas: [{
id: "CA-AB", value: 3645257
},
{
id: "CA-BC", value: 4400057
},
{
id: "CA-MB", value: 1208268
},
{
id: "CA-NB", value: 751171
},
{
id: "CA-NL", value: 514536
},
{
id: "CA-NS", value: 921727
},
{
id: "CA-NT", value: 41462
},
{
id: "CA-NU", value: 31906
},
{
id: "CA-ON", value: 12851821
},
{
id: "CA-PE", value: 140204
},
{
id: "CA-QC", value: 7903001
},
{
id: "CA-SK", value: 1033381
},
{
id: "CA-YT", value: 33897
}],
images: [{ latitude: 45.532, longitude: -73.79, balloonText: "T3695", type: "circle", scale: 0.3 },
{ latitude: 43.7143, longitude: -79.7235, balloonText: "T3623", type: "circle", scale: 0.3 },
{ latitude: 45.5925, longitude: -73.5418, balloonText: "T3705", type: "circle", scale: 0.3 },
{ latitude: 43.4136, longitude: -79.7052, balloonText: "T3670", type: "circle", scale: 0.3 },
{ latitude: 51.0195, longitude: -114.1716, balloonText: "T3754", type: "circle", scale: 0.3 },
{ latitude: 45.7922, longitude: -74.0177, balloonText: "T3657", type: "circle", scale: 0.3 },
{ latitude: 42.3974, longitude: -82.2122, balloonText: "T3533", type: "circle", scale: 0.3 }],
// zoomLevel: 3.37137, // insert the values...
//zoomLatitude: 52.124368, // from the alert box...
//zoomLongitude: -96.251201,// here
};
map.dataProvider = dataProvider;
map.objectList = {
container: "listdiv"
};
map.areasSettings = {
autoZoom: false,
color: "#CDCDCD",
colorSolid: "#5EB7DE",
//selectedColor: "#5EB7DE",
//outlineColor: "#666666",
//rollOverColor: "#88CAE7",
//rollOverOutlineColor: "#FFFFFF",
selectable: true
};
map.ZoomControl = { buttonFillColor: '#CCCCCC' };
map.areasSettings = {
autoZoom: true,
//This is the parameter to be modified to change the Color of the state when SELECTED
selectedColor: "#cc9900",
//This is the parameter to be modified to change the Color of the MAP
color: '#CCFF00',
//This is the parameter to be modified to change the Color of the state when ROLLING OVER
rollOverColor: '#009900',
rollOverOutlineColor: '#009900'
};
map.mouseWheelZoomEnabled = true;
map.write("mapdiv");
});
The solution for your request in the tip section on the amchart web site.
http://www.amcharts.com/tips/weather-map/
I copy here part of the code. The key is creating an images array and the imageURL element.
var map = AmCharts.makeChart("chartdiv", {
type: "map",
"theme": "none",
pathToImages: "http://www.amcharts.com/lib/3/images/",
dataProvider: {
map: "worldLow",
zoomLevel: 5.5,
zoomLongitude: 10,
zoomLatitude: 52,
images: [{
latitude: 40.416775,
longitude: -3.703790,
imageURL: "http://extra.amcharts.com/images/weather/weather-rain.png",
width: 32,
height: 32,
label: "Madrid: +22C"
}, {
latitude: 48.856614,
longitude: 2.352222,
imageURL: "http://extra.amcharts.com/images/weather/weather-storm.png",
width: 32,
height: 32,
label: "Paris: +18C"
},#### More cities
{
latitude: 59.329323,
longitude: 18.068581,
imageURL: "http://extra.amcharts.com/images/weather/weather-rain.png",
width: 32,
height: 32,
label: "Stockholm: +8C"
}]
},
imagesSettings: {
labelRollOverColor: "#000",
labelPosition: "bottom"
},
areasSettings: {
rollOverOutlineColor: "#FFFFFF",
rollOverColor: "#CC0000",
alpha:0.8
}
});
The corresponding HTML code would be:
<script type="text/javascript" src="http://www.amcharts.com/lib/3/ammap.js"></script>
<script type="text/javascript" src="http://www.amcharts.com/lib/3/maps/js/worldLow.js"></script>
<script type="text/javascript" src="http://www.amcharts.com/lib/3/themes/none.js"></script>
<div id="chartdiv"></div>

Categories

Resources