如何编辑绑定到多边形对象的弹出窗口
How do I edit the popups bound to a polygon object
目前,无论我在地图上单击什么地方,都会出现一个带有国家名称的弹出窗口。该国家/地区由一个 geoJSON 文件确定,该文件具有名称和 multi-polygon
lnglat
坐标,这些坐标设置每个国家/地区的边界,这样我就可以单独输入每个国家/地区。
但是,我希望每个弹出窗口都绑定到传单多边形以显示从不同 API(例如 REST 国家和受保护星球)提供的各种信息。尽管如此,我似乎无法弄清楚如何。我更愿意在页面加载时执行此操作,就好像每次用户单击一个国家/地区时我都这样做一样,这可能会导致每次单击一个国家/地区时调用 API 时不必要的等待时间。
基本上我希望代码按如下方式流动:用户点击国家(multi-polygon
对象)-> 绑定到 feature/object 的弹出窗口具有与在开始时调用的国家相关的数据页面加载(通过名称或 PHP 例程中的 ISO_a2)或者当用户单击对象时调用一个函数来检索该信息并使用该信息填充弹出窗口。
//Populating <select>
$(function () {
$.get('libs/json/countryBorders.geo.json').done(function (data) {
data.features.forEach(function (feature) {
$("<option>", {
value: feature.properties.iso_a2,
text: feature.properties.name
}).appendTo("#countrySelect");
});
});
});
console.log("Select Function Loaded.");
//Mapping Borders + Popups
function addDataToMap(data, mymap) {
var myStyle = {
"color": "#36454f",
"weight": 2,
"opacity": 0,
"fillOpacity": 0
};
L.geoJson(data, {
style: myStyle,
onEachFeature: function (feature, mymap) {
var popupFeatureName = feature.properties.name;
var popup = L.popup()
.setContent
(
"<div id='popupContent'>"
+ popupFeatureName +
"</div>"
)
.openOn(mymap);
var popupOptions =
{
'maxWidth': '500',
'className' : 'custom'
}
mymap.bindPopup(popup, popupOptions)
}
}).addTo(mymap);
};
$.getJSON("libs/json/countryBorders.geo.json", function(data) { addDataToMap(data, mymap); });
上下文,我是这个问题的原作者
我通过严格的反复试验设法解决了我的问题,并制定了一个有效的,尽管是一段令人费解的代码。
最大的问题是 Leaflet.js' 弹出内容只接受字符串。因此,即使在 onEachFeature
之外定义变量也会产生有关值被设置为 null
的错误,并且函数将无法工作,或者我会收到类似“appendChild 不是函数”的错误。
对于这种复杂情况,我不得不尝试创建一个解决方法,结果产生了 3 种不同的解决方案。
我将 运行 按时间顺序记下我的 3 个解决方案:
//Initial Attempt
/*"<table><tr><th class='display-4'>" + f.properties.name + "</th></tr>" +
"<tr><td class='font-weight-bold'>Capital:</td><td>" + result["capital"] + "</td></tr>" +
"<tr><td class='font-weight-bold'>Population:</td><td>" + popStr + "</td></tr>" +
"<tr><td class='font-weight-bold'>Demonym:</td><td>" + result["demonym"] + "</td></tr>" +
"<tr><td class='font-weight-bold'>Languages:</td><td>" + result["languages"] + "</td></tr>" +
"<tr><td class='font-weight-bold'>Region:</td><td>" + result["region"] + "</td></tr>";*/
虽然 table 方法有效,但它并不容易阅读,我决定更改我的 CSS 样式以利用 Bootstrap,这更容易指定每一行作为 div
.
//Second Attempt
/*"<div class='container' id='appendButton'>" +
"<div class='h3'>" + f.properties.name + "</div>" +
"<div class='row'>" +
"<div class='col'>Capital:</div>" +
"<div class='col'>" + result["capital"] + "</div>" +
"</div>" +
"<div class='row'>" +
"<div class='col'>Population:</div>" +
"<div class='col'>" + popStr + "</div>" +
"</div>" +
"<div class='row'>" +
"<div class='col'>Demonym:</div>" +
"<div class='col'>" + result["demonym"] + "</div>" +
"</div>" +
"<div class='row'>" +
"<div class='col'>Language:</div>" +
"<div class='col'>" + result["languages"] + "</div>" +
"</div>" +
"<div class='row'>" +
"<div class='col'>Region:</div>" +
"<div class='col'>" + result["region"] + "</div>" +
"</div><br/>" + "<button onclick='getProtectedPlanetAPI(f)' id='APIButton'>Protected Planet</button>" + //Button didn't work
"</div>";*/
如您所见,虽然这有效并且看起来更整洁且放在一起,但按钮不起作用。当尝试在地图或弹出窗口上呈现按钮时,这似乎是 Leaflet 的常见或已知问题。
终于,我找到了一个更好的解决方案。该按钮功能齐全,虽然它包含更多代码行,但您会发现它可能是解决弹出内容问题的最佳方式。同样,通常,这在实际应用程序中是更好的做法。
function onEachFeature(f,l){
var isoa3 = f.properties.iso_a3;
var popupContent = "";
$.ajax({
url: "libs/php/getRESTCountryInfo.php",
type: 'POST',
dataType: 'json',
data: {
iso: isoa3
},
success: function(result) {
// console.log(JSON.stringify(result));
// console.log("JSON stringified");
let pop = result["population"];
let popStr = pop.toLocaleString("en-US");
//Popup Content
var popupCreateContainingDivElement = document.createElement("div");
popupCreateContainingDivElement.className = "container";
var popupCreateMainDivElement = document.createElement("div");
popupCreateMainDivElement.className = "container";
var popupCreateCountryNameHeading = document.createElement("div");
popupCreateCountryNameHeading.innerHTML = f.properties.name;
popupCreateCountryNameHeading.className = "h3";
var popupCreateCapitalTR = document.createElement("div");
popupCreateCapitalTR.className = "row";
var popupCreateCapitalTD = document.createElement("div");
popupCreateCapitalTD.className = "col";
popupCreateCapitalTD.innerText = "Capital:";
var popupCreateCapitalResultTD = document.createElement("div");
popupCreateCapitalResultTD.className = "col";
popupCreateCapitalResultTD.innerText = result["capital"];
popupCreateCapitalTR.appendChild(popupCreateCapitalTD);
popupCreateCapitalTR.appendChild(popupCreateCapitalResultTD);
var popupCreatePopulationTR = document.createElement("div");
popupCreatePopulationTR.className = "row";
var popupCreatePopulationTD = document.createElement("div");
popupCreatePopulationTD.className = "col";
popupCreatePopulationTD.innerText = "Population:";
var popupCreatePopulationResultTD = document.createElement("div");
popupCreatePopulationResultTD.className = "col";
popupCreatePopulationResultTD.innerText = popStr;
popupCreatePopulationTR.appendChild(popupCreatePopulationTD);
popupCreatePopulationTR.appendChild(popupCreatePopulationResultTD);
var popupCreateDemonymTR = document.createElement("div");
popupCreateDemonymTR.className = "row";
var popupCreateDemonymTD = document.createElement("div");
popupCreateDemonymTD.className = "col";
popupCreateDemonymTD.innerText = "Demonym:"
var popupCreateDemonymResultTD = document.createElement("div");
popupCreateDemonymResultTD.className = "col";
popupCreateDemonymResultTD.innerText = result["demonym"];
popupCreateDemonymTR.appendChild(popupCreateDemonymTD);
popupCreateDemonymTR.appendChild(popupCreateDemonymResultTD);
var popupCreateLanguagesTR = document.createElement("div");
popupCreateLanguagesTR.className = "row";
var popupCreateLanguagesTD = document.createElement("div");
popupCreateLanguagesTD.className = "col";
popupCreateLanguagesTD.innerText = "Languages:";
var popupCreateLanguagesResultTD = document.createElement("div");
popupCreateLanguagesResultTD.className = "col";
popupCreateLanguagesResultTD.innerText = result["languages"];
popupCreateLanguagesTR.appendChild(popupCreateLanguagesTD);
popupCreateLanguagesTR.appendChild(popupCreateLanguagesResultTD);
var popupCreateRegionTR = document.createElement("div");
popupCreateRegionTR.className = "row";
var popupCreateRegionTD = document.createElement("div");
popupCreateRegionTD.className = "col";
popupCreateRegionTD.innerText = "Region:";
var popupCreateRegionResultTD = document.createElement("div");
popupCreateRegionResultTD.className = "col";
popupCreateRegionResultTD.innerText = result["region"];
popupCreateRegionTR.appendChild(popupCreateRegionTD);
popupCreateRegionTR.appendChild(popupCreateRegionResultTD);
var popupCreateAdditionalInfoButton = document.createElement("button");
popupCreateAdditionalInfoButton.innerHTML = "Protected Planet";
popupCreateAdditionalInfoButton.onclick = getProtectedPlanetAPI;
popupCreateMainDivElement.appendChild(popupCreateCountryNameHeading);
popupCreateMainDivElement.appendChild(popupCreateCapitalTR);
popupCreateMainDivElement.appendChild(popupCreatePopulationTR);
popupCreateMainDivElement.appendChild(popupCreateDemonymTR);
popupCreateMainDivElement.appendChild(popupCreateLanguagesTR);
popupCreateMainDivElement.appendChild(popupCreateRegionTR);
popupCreateMainDivElement.appendChild(popupCreateAdditionalInfoButton);
popupCreateContainingDivElement.appendChild(popupCreateMainDivElement);
var expandedSection = document.createElement("div");
expandedSection.className = "container";
expandedSection.id = "expandedSection";
popupCreateContainingDivElement.appendChild(expandedSection);
if (result.status.name == "ok") {
popupContent = popupCreateContainingDivElement;
var popupOptions =
{
'minWidth': '300',
'className' : 'custom'
}
l.bindPopup(popupContent, popupOptions);
}
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
}
});
目前,无论我在地图上单击什么地方,都会出现一个带有国家名称的弹出窗口。该国家/地区由一个 geoJSON 文件确定,该文件具有名称和 multi-polygon
lnglat
坐标,这些坐标设置每个国家/地区的边界,这样我就可以单独输入每个国家/地区。
但是,我希望每个弹出窗口都绑定到传单多边形以显示从不同 API(例如 REST 国家和受保护星球)提供的各种信息。尽管如此,我似乎无法弄清楚如何。我更愿意在页面加载时执行此操作,就好像每次用户单击一个国家/地区时我都这样做一样,这可能会导致每次单击一个国家/地区时调用 API 时不必要的等待时间。
基本上我希望代码按如下方式流动:用户点击国家(multi-polygon
对象)-> 绑定到 feature/object 的弹出窗口具有与在开始时调用的国家相关的数据页面加载(通过名称或 PHP 例程中的 ISO_a2)或者当用户单击对象时调用一个函数来检索该信息并使用该信息填充弹出窗口。
//Populating <select>
$(function () {
$.get('libs/json/countryBorders.geo.json').done(function (data) {
data.features.forEach(function (feature) {
$("<option>", {
value: feature.properties.iso_a2,
text: feature.properties.name
}).appendTo("#countrySelect");
});
});
});
console.log("Select Function Loaded.");
//Mapping Borders + Popups
function addDataToMap(data, mymap) {
var myStyle = {
"color": "#36454f",
"weight": 2,
"opacity": 0,
"fillOpacity": 0
};
L.geoJson(data, {
style: myStyle,
onEachFeature: function (feature, mymap) {
var popupFeatureName = feature.properties.name;
var popup = L.popup()
.setContent
(
"<div id='popupContent'>"
+ popupFeatureName +
"</div>"
)
.openOn(mymap);
var popupOptions =
{
'maxWidth': '500',
'className' : 'custom'
}
mymap.bindPopup(popup, popupOptions)
}
}).addTo(mymap);
};
$.getJSON("libs/json/countryBorders.geo.json", function(data) { addDataToMap(data, mymap); });
上下文,我是这个问题的原作者
我通过严格的反复试验设法解决了我的问题,并制定了一个有效的,尽管是一段令人费解的代码。
最大的问题是 Leaflet.js' 弹出内容只接受字符串。因此,即使在 onEachFeature
之外定义变量也会产生有关值被设置为 null
的错误,并且函数将无法工作,或者我会收到类似“appendChild 不是函数”的错误。
对于这种复杂情况,我不得不尝试创建一个解决方法,结果产生了 3 种不同的解决方案。
我将 运行 按时间顺序记下我的 3 个解决方案:
//Initial Attempt
/*"<table><tr><th class='display-4'>" + f.properties.name + "</th></tr>" +
"<tr><td class='font-weight-bold'>Capital:</td><td>" + result["capital"] + "</td></tr>" +
"<tr><td class='font-weight-bold'>Population:</td><td>" + popStr + "</td></tr>" +
"<tr><td class='font-weight-bold'>Demonym:</td><td>" + result["demonym"] + "</td></tr>" +
"<tr><td class='font-weight-bold'>Languages:</td><td>" + result["languages"] + "</td></tr>" +
"<tr><td class='font-weight-bold'>Region:</td><td>" + result["region"] + "</td></tr>";*/
虽然 table 方法有效,但它并不容易阅读,我决定更改我的 CSS 样式以利用 Bootstrap,这更容易指定每一行作为 div
.
//Second Attempt
/*"<div class='container' id='appendButton'>" +
"<div class='h3'>" + f.properties.name + "</div>" +
"<div class='row'>" +
"<div class='col'>Capital:</div>" +
"<div class='col'>" + result["capital"] + "</div>" +
"</div>" +
"<div class='row'>" +
"<div class='col'>Population:</div>" +
"<div class='col'>" + popStr + "</div>" +
"</div>" +
"<div class='row'>" +
"<div class='col'>Demonym:</div>" +
"<div class='col'>" + result["demonym"] + "</div>" +
"</div>" +
"<div class='row'>" +
"<div class='col'>Language:</div>" +
"<div class='col'>" + result["languages"] + "</div>" +
"</div>" +
"<div class='row'>" +
"<div class='col'>Region:</div>" +
"<div class='col'>" + result["region"] + "</div>" +
"</div><br/>" + "<button onclick='getProtectedPlanetAPI(f)' id='APIButton'>Protected Planet</button>" + //Button didn't work
"</div>";*/
如您所见,虽然这有效并且看起来更整洁且放在一起,但按钮不起作用。当尝试在地图或弹出窗口上呈现按钮时,这似乎是 Leaflet 的常见或已知问题。
终于,我找到了一个更好的解决方案。该按钮功能齐全,虽然它包含更多代码行,但您会发现它可能是解决弹出内容问题的最佳方式。同样,通常,这在实际应用程序中是更好的做法。
function onEachFeature(f,l){
var isoa3 = f.properties.iso_a3;
var popupContent = "";
$.ajax({
url: "libs/php/getRESTCountryInfo.php",
type: 'POST',
dataType: 'json',
data: {
iso: isoa3
},
success: function(result) {
// console.log(JSON.stringify(result));
// console.log("JSON stringified");
let pop = result["population"];
let popStr = pop.toLocaleString("en-US");
//Popup Content
var popupCreateContainingDivElement = document.createElement("div");
popupCreateContainingDivElement.className = "container";
var popupCreateMainDivElement = document.createElement("div");
popupCreateMainDivElement.className = "container";
var popupCreateCountryNameHeading = document.createElement("div");
popupCreateCountryNameHeading.innerHTML = f.properties.name;
popupCreateCountryNameHeading.className = "h3";
var popupCreateCapitalTR = document.createElement("div");
popupCreateCapitalTR.className = "row";
var popupCreateCapitalTD = document.createElement("div");
popupCreateCapitalTD.className = "col";
popupCreateCapitalTD.innerText = "Capital:";
var popupCreateCapitalResultTD = document.createElement("div");
popupCreateCapitalResultTD.className = "col";
popupCreateCapitalResultTD.innerText = result["capital"];
popupCreateCapitalTR.appendChild(popupCreateCapitalTD);
popupCreateCapitalTR.appendChild(popupCreateCapitalResultTD);
var popupCreatePopulationTR = document.createElement("div");
popupCreatePopulationTR.className = "row";
var popupCreatePopulationTD = document.createElement("div");
popupCreatePopulationTD.className = "col";
popupCreatePopulationTD.innerText = "Population:";
var popupCreatePopulationResultTD = document.createElement("div");
popupCreatePopulationResultTD.className = "col";
popupCreatePopulationResultTD.innerText = popStr;
popupCreatePopulationTR.appendChild(popupCreatePopulationTD);
popupCreatePopulationTR.appendChild(popupCreatePopulationResultTD);
var popupCreateDemonymTR = document.createElement("div");
popupCreateDemonymTR.className = "row";
var popupCreateDemonymTD = document.createElement("div");
popupCreateDemonymTD.className = "col";
popupCreateDemonymTD.innerText = "Demonym:"
var popupCreateDemonymResultTD = document.createElement("div");
popupCreateDemonymResultTD.className = "col";
popupCreateDemonymResultTD.innerText = result["demonym"];
popupCreateDemonymTR.appendChild(popupCreateDemonymTD);
popupCreateDemonymTR.appendChild(popupCreateDemonymResultTD);
var popupCreateLanguagesTR = document.createElement("div");
popupCreateLanguagesTR.className = "row";
var popupCreateLanguagesTD = document.createElement("div");
popupCreateLanguagesTD.className = "col";
popupCreateLanguagesTD.innerText = "Languages:";
var popupCreateLanguagesResultTD = document.createElement("div");
popupCreateLanguagesResultTD.className = "col";
popupCreateLanguagesResultTD.innerText = result["languages"];
popupCreateLanguagesTR.appendChild(popupCreateLanguagesTD);
popupCreateLanguagesTR.appendChild(popupCreateLanguagesResultTD);
var popupCreateRegionTR = document.createElement("div");
popupCreateRegionTR.className = "row";
var popupCreateRegionTD = document.createElement("div");
popupCreateRegionTD.className = "col";
popupCreateRegionTD.innerText = "Region:";
var popupCreateRegionResultTD = document.createElement("div");
popupCreateRegionResultTD.className = "col";
popupCreateRegionResultTD.innerText = result["region"];
popupCreateRegionTR.appendChild(popupCreateRegionTD);
popupCreateRegionTR.appendChild(popupCreateRegionResultTD);
var popupCreateAdditionalInfoButton = document.createElement("button");
popupCreateAdditionalInfoButton.innerHTML = "Protected Planet";
popupCreateAdditionalInfoButton.onclick = getProtectedPlanetAPI;
popupCreateMainDivElement.appendChild(popupCreateCountryNameHeading);
popupCreateMainDivElement.appendChild(popupCreateCapitalTR);
popupCreateMainDivElement.appendChild(popupCreatePopulationTR);
popupCreateMainDivElement.appendChild(popupCreateDemonymTR);
popupCreateMainDivElement.appendChild(popupCreateLanguagesTR);
popupCreateMainDivElement.appendChild(popupCreateRegionTR);
popupCreateMainDivElement.appendChild(popupCreateAdditionalInfoButton);
popupCreateContainingDivElement.appendChild(popupCreateMainDivElement);
var expandedSection = document.createElement("div");
expandedSection.className = "container";
expandedSection.id = "expandedSection";
popupCreateContainingDivElement.appendChild(expandedSection);
if (result.status.name == "ok") {
popupContent = popupCreateContainingDivElement;
var popupOptions =
{
'minWidth': '300',
'className' : 'custom'
}
l.bindPopup(popupContent, popupOptions);
}
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
}
});