leaflet-simple-map-screenshoter
leaflet-simple-map-screenshoter copied to clipboard
'Cannot read properties of undefined' error when exporting updated map image after AJAX statement
(by Google Translator) I have a page that generates the first map with the default filters and the user can also apply filters to update the map. The problem is that when I update my map via AJAX instruction, I get an error alert
TypeError: Cannot read properties of undefined (reading 'style')
and which increases the amount of alerts as the user applies new filters. Images are generated normally even with the error. How can I solve this problem? Despite the problem, I really liked this library. It's quite flexible and effective.
My code below:
function generateMyMap(zoom, centerMap, title, dataSource, collectionDate, user) {
// checks for authenticated user and applies temporary map name
if (user) {
mapUrl = "../assets/js/temp-geojson/" + user + "|geojson.js";
} else {
mapUrl = "../assets/js/temp-geojson/geojson.js";
}
// delete the old map before applying the new map with selected filters
if (map && map.remove) {
map.off();
map.remove();
}
// generate map attributes
map = L.map('map').setView(centerMap, zoom);
map.spin(true);
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
minZoom: 3,
maxZoom: 18,
attribution: '© <a href="http://openstreetmap.org">OpenStreetMap</a> contributors',
id: 'mapbox/light-v9',
tileSize: 512,
zoomOffset: -1
}).addTo(map);
// control that shows state info on hover
var info = L.control();
info.onAdd = function (map) {
this._div = L.DomUtil.create('div', 'info');
this.update();
return this._div;
};
info.update = function (props) {
this._div.innerHTML = '<h6><b>' + title + '</b></h6>' + (props ?
'<b>' + props.local + '</b>: ' +
'<br>' + props.values.toLocaleString() + '%'
: '<span>Mouse over the desired location</span>');
};
info.addTo(map);
// get color depending on selection value
function getColor(d) {
return d > 30 ? '#33C009' :
d > 20 ? '#73D50B' :
d > 10 ? '#ABEC08' :
d > 0 ? '#E1EB09' :
d > -10 ? '#F3BC01' :
d > -20 ? '#F3A201' :
d > -30 ? '#F36401' :
'#F30101';
}
function style(feature) {
return {
weight: 2,
opacity: 1,
color: 'white',
dashArray: '3',
fillOpacity: 0.7,
fillColor: getColor(feature.properties.values)
};
}
function highlightFeature(e) {
var layer = e.target;
layer.setStyle({
weight: 5,
color: '#666',
dashArray: '',
fillOpacity: 0.7
});
if (!L.Browser.ie && !L.Browser.opera && !L.Browser.edge) {
layer.bringToFront();
}
info.update(layer.feature.properties);
}
// generate map from a GeoJSON file
var geojson;
function resetHighlight(e) {
geojson.resetStyle(e.target);
info.update();
}
function zoomToFeature(e) {
map.fitBounds(e.target.getBounds());
}
function onEachFeature(feature, layer) {
layer.on({
mouseover: highlightFeature,
mouseout: resetHighlight,
click: function () {
layer.bindPopup('<b>' + feature.properties.local + '</b>' +
'<br>' + feature.properties.values.toLocaleString() + '%').openPopup()
}
});
}
geojson = new L.GeoJSON.AJAX(mapUrl, {
style: style,
onEachFeature: onEachFeature
});
geojson.addTo(map);
collectionDate = collectionDate.split("-");
collectionDate = collectionDate[0];
map.attributionControl.addAttribution();
$('#data-source-chart').html('Data Source: ' + dataSource + ' (' + collectionDate + ')');
var legend = L.control({position: 'bottomright'});
legend.onAdd = function (map) {
var div = L.DomUtil.create('div', 'info legend'),
grades = [-30, -20, -10, 0, 10, 20, 30, 40],
labels = [],
from, to;
for (var i = 0; i < grades.length; i++) {
from = grades[i];
to = grades[i + 1];
labels.push(
'<i style="background:' + getColor(from) + '"></i> ' +
from + (to ? '% – ' + to + '%' : '%+'));
}
div.innerHTML = labels.join('<br>');
return div;
};
legend.addTo(map);
map.spin(false);
/************** Export map to image ****************/
// init plugin
var simpleMapScreenshoter = L.simpleMapScreenshoter({
hidden: true, // hide screen btn on map
hideElementsWithSelectors: ['.leaflet-control-zoom', '.leaflet-control span']
}).addTo(map);
// return as blob
document.getElementById('btn-download-chart').addEventListener('click', function () {
simpleMapScreenshoter.takeScreen('blob', {}).then(blob => {
saveAs(blob, 'my-map.png')
}).catch(e => {
alert(e.toString())
})
})
// listen on fired error or catch error in prev promise
map.on('simpleMapScreenshoter.error', function (event) {
var el = document.createElement('div')
el.classList.add('create-screen-error')
el.innerHTML = event.e.toString()
document.getElementById('screens').appendChild(el)
})
/******************* ***************************/
// deletes the GeoJSON file after generating the map
geojson.on("data:loaded", function () {
deleteTempGeoJSON();
});
}