使用 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/

长话短说,您使用的源同时包含 PolygonMultiPolygon 要素,因此您选择的要素坐标有时是一个数组,有时是一个多维数组。

有不同的方法可以解决这个问题...

又快又脏

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);

如果是PointPolygonMultiPolygon...

,这将独立找到特征中心

PS.- 如果这个答案解决了您的问题,请将其标记为“答案已接受”,这样也可以帮助其他用户知道它是正确的解决方案。