Я показываю карту Соединенных Штатов с использованием Leaflet. js, где, если пользователь нажимает на штат, карта увеличивается для просмотра всех переписных участков штата.
Код загружает данные переписи GeoJSON (161,3 МБ), используя 51 запрос XMLHttp в WebWorker, а также состояния Geo JSON (523 КБ), используя 1 запрос XMLHttp в основном потоке.
Существует значительная задержка при первой загрузке страницы, что (EDIT) мне подходит, потому что это неизбежно, учитывая подход, который я использую, и зависит от соединения пользователя inte rnet. Однако только в Firefox (а не в Chrome или Safari) возникают проблемы с памятью. Каждый раз, когда я обновляю sh страницу, память в браузере накапливается, пока браузер не зависнет. Одна только память вкладки выглядит нормально, потому что когда я go до about:performance
(диспетчер задач Firefox) и наблюдаю за перезагрузкой страницы, память кажется одинаковой каждый раз. Но в мониторе активности Ma c я вижу увеличение памяти с каждой перезагрузкой.
Я пытался явно удалить переменные в своем коде, но не могу понять, что здесь происходит. Можем ли мы исправить это с помощью Firefox?
Полный HTML, SSCCE:
<head>
<style>
body {
padding: 0;
margin: 0;
}
#map {
height: 100vh;
width: 100vw;
}
</style>
<!-- Leaflet -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js" integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew==" crossorigin=""></script>
<!-- my code -->
<script src="test_script.js"></script>
</head>
<body>
<div id="map"></div>
</body>
Полный JS, SSCCE:
window.onload = function() {
/*------------------------------------------------
-------------- Initialize variables --------------
------------------------------------------------*/
var mapboxAccessToken = 'pk.eyJ1IjoiYnJpZW5uYWtoIiwiYSI6ImNqbXRsNjN0aTAxZXAzbG13bmh0dGFjNm0ifQ.98TAXgq4Rg1LpM2Oq1rlWw';
function reqListener() {
statesData = JSON.parse(this.response);
}
// Get main data
var xhr = new XMLHttpRequest();
var url = 'http://briennakh.me/accessibility-maps/data/us_states_edited.json?v=' + new Date().getTime()
xhr.addEventListener('load', reqListener);
xhr.open('GET', url, false);
xhr.send();
/*------------------------------------------------
-------------- Create map ------------------------
------------------------------------------------*/
// Create basemap
var basemap = L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
id: 'mapbox/light-v9',
attribution: '',
tileSize: 512,
zoomOffset: -1,
maxZoom: 18,
accessToken: mapboxAccessToken,
});
// Create map
var map = L.map('map', {
center: new L.LatLng(37.8, -96),
zoom: 4,
layers: [basemap],
});
var stateLayer = L.geoJson(statesData, {
style: stateStyle,
onEachFeature: onEachState
}).addTo(map);
var censusTractLayers = {};
if (typeof(Worker) !== "undefined") {
w = new Worker('worker.js'); // to test worker, must serve on localhost, otherwise Security Error
// Respond to message sent back from worker
w.onmessage = function(e) {
var state = e.data;
console.log('Received message from worker for ' + state.name)
censusTractLayers[state.name] = L.geoJson(state, {
style: tractStyle,
onEachFeature: onEachTract
});
}
} else {
// will need to inform user they need an updated browser
console.log('No support for web worker.');
}
// Load each state's census tracts in the background
w.postMessage(statesData.features);
/*------------------------------------------------
-------------- Define styles ---------------------
------------------------------------------------*/
function tractStyle(feature) {
return {
fillColor: 'grey',
weight: .5, // no border
opacity: 1,
color: 'white',
dashArray: '1',
fillOpacity: 0.7
}
}
function stateStyle(feature) {
return {
fillColor: 'grey',
weight: 2,
opacity: 1,
color: 'white',
dashArray: '3',
fillOpacity: 0.7
};
}
/*------------------------------------------------
-------------- Define event handlers -------------
------------------------------------------------*/
function onEachState(feature, layer) {
layer.on({
mouseover: function(e) {
highlightFeature(e);
},
mouseout: function(e) {
var feature = e.target;
stateLayer.resetStyle(feature);
},
click: function(e) {
map.fitBounds(e.target.getBounds());
// Add census tract layer to map if it has already been loaded
if (feature.properties.name in censusTractLayers) {
censusTractLayers[feature.properties.name].addTo(map);
} else {
console.log('Not loaded yet');
}
}
});
}
function onEachTract(feature, layer) {
layer.on({
mouseover: function(e) {
highlightFeature(e);
},
mouseout: function(e) {
var feature = e.target;
for (i in censusTractLayers) {
if(censusTractLayers[i].hasLayer(feature)) {
censusTractLayers[i].resetStyle(feature);
}
}
}
});
}
function highlightFeature(e) {
var feature = e.target;
feature.setStyle({
weight: 5,
color: '#666',
dashArray: '',
fillOpacity: 0.7
});
if (!L.Browser.ie && !L.Browser.opera && !L.Browser.edge) {
feature.bringToFront(); // to prevent feature overlaps
}
}
}
JS для веб-работника:
function reqListener() {
postMessage(this.response);
}
onmessage = function(e) {
console.log('Message received from main script.');
for (var i in e.data) {
state = e.data[i].properties.name;
var xhr = new XMLHttpRequest();
var url = 'http://briennakh.me/accessibility-maps/data/census tracts/geojsons/' + state + '.json?v=' + new Date().getTime();
xhr.addEventListener('load', reqListener);
xhr.open('GET', url);
xhr.responseType = 'json';
xhr.send();
}
}