使用 mapbox gl js 在地图上显示侧面列表中所选项目的弹出窗口
Show popup on the map for the selected item in the side list using the mapbox gl js
我遵循了本教程 "Filter features within map view" 并设法使其适应我的数据,这些数据是多边形而不是点。
但是,侧边菜单上的弹出窗口没有显示,当我将鼠标放在其中一个位置上时,弹出窗口没有出现在地图上,指示该位置。
我认为的问题是因为它是一个多边形而不是一个点(一对坐标)代码无法显示位置,控制台中的错误是:
"Uncaught Error:` LngLatLike` argument must be specified as a LngLat instance, an object {lng: <lng>, lat: <lat>}, an object {lon: <lng>, lat: <lat>}, or an array of [<lng>, <lat>] "
在地图弹出窗口中,我将其从“.setLngLat (feature.geometry.coordinates)
”更改为
到“.setLngLat (e.lngLat)
”,它起作用了,但在侧面菜单的弹出窗口中不起作用。
刚开始学习javascript没找到解决办法,想过从多边形中提取质心,但不知道怎么做。
生成弹窗的代码:
var prop = feature.properties;
var item = document.createElement('a');
item.href = prop.wikipedia;
item.target = '_blank';
item.textContent = prop.NM_UF + ' (' + prop.SIGLA_UF + ')';
item.addEventListener('mouseover', function () {
// Highlight corresponding feature on the map
popup
.setLngLat(feature.geometry.coordinates)
.setText(
feature.properties.NM_UF +
' (' +
feature.properties.SIGLA_UF +
')'
)
.addTo(map);
});
listingEl.appendChild(item);
});
这是一个像代码一样的codepen:
https://codepen.io/hugonbgg/pen/PoNwWVj and the debug: https://codepen.io/hugonbgg/debug/PoNwWVj/
长话短说,您使用的源同时包含 Polygon
和 MultiPolygon
要素,因此您选择的要素坐标有时是一个数组,有时是一个多维数组。
有不同的方法可以解决这个问题...
又快又脏
popup
.setLngLat(feature.geometry.coordinates[0][0]) //just add [0][0]
.setText(
feature.properties.NM_UF +
' (' +
feature.properties.SIGLA_UF +
')'
)
.addTo(map);
这很有效,但将弹出提示定位在第一个多边形的第一个点上...不一定是最好的,但它确实有效。
第二种方法是我会做的...
通过一种方法找到任意特征的中心
我根据您的 codepen 创建了这个 codepen,并添加了 getFeatureCenter
方法。
function getFeatureCenter(feature) {
let center = [];
let latitude = 0;
let longitude = 0;
let height = 0;
let coordinates = [];
feature.geometry.coordinates.forEach(function (c) {
let dupe = [];
if (feature.geometry.type === "MultiPolygon")
dupe.push(...c[0]); //deep clone to avoid modifying the original array
else
dupe.push(...c); //deep clone to avoid modifying the original array
dupe.splice(-1, 1); //features in mapbox repeat the first coordinates at the end. We remove it.
coordinates = coordinates.concat(dupe);
});
if (feature.geometry.type === "Point") {
center = coordinates[0];
}
else {
coordinates.forEach(function (c) {
latitude += c[0];
longitude += c[1];
});
center = [latitude / coordinates.length, longitude / coordinates.length];
}
return center;
}
然后更改对弹出窗口的调用
popup
.setLngLat(getFeatureCenter(feature)) //call the new method and enjoy!
.setText(
feature.properties.NM_UF +
' (' +
feature.properties.SIGLA_UF +
')'
)
.addTo(map);
如果是Point
、Polygon
或MultiPolygon
...
,这将独立找到特征中心
PS.- 如果这个答案解决了您的问题,请将其标记为“答案已接受”,这样也可以帮助其他用户知道它是正确的解决方案。
我遵循了本教程 "Filter features within map view" 并设法使其适应我的数据,这些数据是多边形而不是点。
但是,侧边菜单上的弹出窗口没有显示,当我将鼠标放在其中一个位置上时,弹出窗口没有出现在地图上,指示该位置。 我认为的问题是因为它是一个多边形而不是一个点(一对坐标)代码无法显示位置,控制台中的错误是:
"Uncaught Error:` LngLatLike` argument must be specified as a LngLat instance, an object {lng: <lng>, lat: <lat>}, an object {lon: <lng>, lat: <lat>}, or an array of [<lng>, <lat>] "
在地图弹出窗口中,我将其从“.setLngLat (feature.geometry.coordinates)
”更改为
到“.setLngLat (e.lngLat)
”,它起作用了,但在侧面菜单的弹出窗口中不起作用。
刚开始学习javascript没找到解决办法,想过从多边形中提取质心,但不知道怎么做。
生成弹窗的代码:
var prop = feature.properties;
var item = document.createElement('a');
item.href = prop.wikipedia;
item.target = '_blank';
item.textContent = prop.NM_UF + ' (' + prop.SIGLA_UF + ')';
item.addEventListener('mouseover', function () {
// Highlight corresponding feature on the map
popup
.setLngLat(feature.geometry.coordinates)
.setText(
feature.properties.NM_UF +
' (' +
feature.properties.SIGLA_UF +
')'
)
.addTo(map);
});
listingEl.appendChild(item);
});
这是一个像代码一样的codepen: https://codepen.io/hugonbgg/pen/PoNwWVj and the debug: https://codepen.io/hugonbgg/debug/PoNwWVj/
长话短说,您使用的源同时包含 Polygon
和 MultiPolygon
要素,因此您选择的要素坐标有时是一个数组,有时是一个多维数组。
有不同的方法可以解决这个问题...
又快又脏
popup
.setLngLat(feature.geometry.coordinates[0][0]) //just add [0][0]
.setText(
feature.properties.NM_UF +
' (' +
feature.properties.SIGLA_UF +
')'
)
.addTo(map);
这很有效,但将弹出提示定位在第一个多边形的第一个点上...不一定是最好的,但它确实有效。
第二种方法是我会做的...
通过一种方法找到任意特征的中心
我根据您的 codepen 创建了这个 codepen,并添加了 getFeatureCenter
方法。
function getFeatureCenter(feature) {
let center = [];
let latitude = 0;
let longitude = 0;
let height = 0;
let coordinates = [];
feature.geometry.coordinates.forEach(function (c) {
let dupe = [];
if (feature.geometry.type === "MultiPolygon")
dupe.push(...c[0]); //deep clone to avoid modifying the original array
else
dupe.push(...c); //deep clone to avoid modifying the original array
dupe.splice(-1, 1); //features in mapbox repeat the first coordinates at the end. We remove it.
coordinates = coordinates.concat(dupe);
});
if (feature.geometry.type === "Point") {
center = coordinates[0];
}
else {
coordinates.forEach(function (c) {
latitude += c[0];
longitude += c[1];
});
center = [latitude / coordinates.length, longitude / coordinates.length];
}
return center;
}
然后更改对弹出窗口的调用
popup
.setLngLat(getFeatureCenter(feature)) //call the new method and enjoy!
.setText(
feature.properties.NM_UF +
' (' +
feature.properties.SIGLA_UF +
')'
)
.addTo(map);
如果是Point
、Polygon
或MultiPolygon
...
PS.- 如果这个答案解决了您的问题,请将其标记为“答案已接受”,这样也可以帮助其他用户知道它是正确的解决方案。