简体   繁体   中英

Leaflet.js Circle Click Event Handler

I am trying to get a circle click event to update 'name' id, but am having trouble getting the sites the "name" variable to change once I click one of the circles. The error that I am getting says "Uncaught TypeError: Cannot read property '3' of undefined", which is coming from this line: var name = e.sites[i].names;

 // Define variables for our base layers var streetmap = L.tileLayer("https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}", { attribution: "Map data &copy; <a href=\"https://www.openstreetmap.org/\">OpenStreetMap</a> contributors, <a href=\"https://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA</a>, Imagery © <a href=\"https://www.mapbox.com/\">Mapbox</a>", maxZoom: 18, id: "mapbox.streets", accessToken: "pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw" }); // satellite map background tile layer var satellitemap = L.tileLayer("https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}", { attribution: "Map data &copy; <a href=\"https://www.openstreetmap.org/\">OpenStreetMap</a> contributors, <a href=\"https://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA</a>, Imagery © <a href=\"https://www.mapbox.com/\">Mapbox</a>", maxZoom: 15, id: "mapbox.satellite", accessToken: "pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw" }); var darkmap = L.tileLayer("https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}", { attribution: "Map data &copy; <a href=\"https://www.openstreetmap.org/\">OpenStreetMap</a> contributors, <a href=\"https://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA</a>, Imagery © <a href=\"https://www.mapbox.com/\">Mapbox</a>", maxZoom: 18, id: "mapbox.dark", accessToken: "pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw" }); // Initialize all of the LayerGroups to be used var layers = { CREEK_SITES: new L.LayerGroup() }; // Create the map with layers var map = L.map("map", { center: [44.953457, -93.502959], zoom: 11, layers: [ layers.CREEK_SITES ] }); // Add 'darkmap' tile layer to the map as default darkmap.addTo(map); // Create an overlay object var overlayMaps = { "Stream Level": layers.CREEK_SITES }; var baseMaps = { "Street Map": streetmap, "Dark Map": darkmap }; L.control.layers(baseMaps, overlayMaps).addTo(map); // CREEK SITES LAYER // ================================================================================================= var sites = [{ names: "CPA01", location: [44.964088, -93.672554], subwatershed: "Painters Creek" }, { names: "CMH04", location: [44.901323, -93.332248], subwatershed: "Minnehaha Creek" }, { names: "CMH24", location: [44.915574, -93.242167], subwatershed: "Minnehaha Creek" } ]; //Change the size and color of circular markers here for (var i = 0; i < sites.length; i++) { circle = new L.circle(sites[i].location, 200, { fillOpacity: 0.8, color: "orange", fillColor: "blue" }).addTo(layers.CREEK_SITES).on("click", circleClick); function circleClick(e) { var name = e.sites[i].names; return document.getElementById('name').innerHTML=name; } } var sites = [{ names: "CPA01", location: [44.964088, -93.672554], subwatershed: "Painters Creek" }, { names: "CMH04", location: [44.901323, -93.332248], subwatershed: "Minnehaha Creek" }, { names: "CMH24", location: [44.915574, -93.242167], subwatershed: "Minnehaha Creek" } ]; for (var i = 0; i < sites.length; i++) { circle = new L.circle(sites[i].location, 200, { fillOpacity: 0.8, color: "orange", fillColor: "blue" }).addTo(layers.CREEK_SITES).on("click", circleClick); function circleClick(e) { var name = e.sites[i].names; return document.getElementById('name').innerHTML=name; } }
 <body> <:-- The div where we will inject our map --> <div id="info"><h1 id="name"></h1></div> <div id="map"></div> <:-- begin snippet: js hide: false console: true babel: false -->

That is caused by a classic misconception of JavaScript scopes.

Your function circleClick is hoisted out of your for loop block; a JS function scope is a parent function block, or the global scope. Same for var .

Therefore when you fire the click event, your function tries to access e.sites , which is undefined since e is the function argument, which value is supplied by Leaflet, which knows nothing about your sites variable. You could directly use sites instead.

Then it tries to access sites[i] , with i being the value left after the for loop, ie 3 since this is the length of your sites array. Instead you should simply embed your desired value in your Layer, so that you can easily retrieve it by accessing the Layer which was clicked, which is provided by Leaflet in the click event argument: https://leafletjs.com/reference-1.6.0.html#event-sourcetarget

function circleClick(e) {
  const name = e.sourceTarget.options.name;
  document.getElementById('name').innerHTML = name;
}

for (let i = 0; i < sites.length; i++) {
  L.circle(sites[i].location, 200, {
    name: sites[i].names, // you can add arbitrary option to embed your data
    fillOpacity: 0.8,
    color: "orange",
    fillColor: "blue"
  }).addTo(layers.CREEK_SITES).on("click", circleClick);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM