使用自定义属性映射框为每个群集标记显示一个弹出窗口

时间:2019-07-15 16:12:03

标签: javascript html mapbox-gl-js

我正在显示带有图像图标的自定义标记,并根据缩放级别显示标记的数量。如何为每个标记添加一个弹出窗口?

这是我用来绘制所有标记的代码。

map.on('load', function () {

    // add a clustered GeoJSON source for a sample set of earthquakes
    map.addSource('earthquakes', {
        "type": "geojson",
        "data": "https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson",
        "cluster": true,
        "clusterRadius": 80
        });


    map.addLayer({
        "id": "cluster",
        "type": "symbol",
        "source": "earthquakes",
        "filter": ["!=", "cluster", true]
        });

    // objects for caching and keeping track of HTML marker objects (for performance)
    var markers = {};
    var markersOnScreen = {};

    function updateMarkers(){
        var newMarkers = {};
        var features = map.querySourceFeatures( 'earthquakes' );

        for ( var i = 0; i < features.length; i++ ) {
            var coords = features[ i ].geometry.coordinates;
            var props = features[ i ].properties;

            if (!props.cluster) continue;
            var id = props.cluster_id;

            var marker = markers[id];

            if (!marker) {
                var el = new Image();
                el.src = 'icon.png';
                el.classList.add( 'mapMarker' );
                el.dataset.type = props.type; // you can use custom data if you have assigned it in the GeoJSON data
                marker = markers[id] = new mapboxgl.Marker({element: el}).setLngLat(coords);

            }

            newMarkers[id] = marker;

            if (!markersOnScreen[id])
                marker.addTo(map);


        }
        // for every marker we've added previously, remove those that are no longer visible
        for (id in markersOnScreen) {
            if (!newMarkers[id])
                markersOnScreen[id].remove();
        }
        markersOnScreen = newMarkers;
    }


    // after the GeoJSON data is loaded, update markers on the screen and do so on every map move/moveend
    map.on('data', function (e) {
        if (e.sourceId !== 'earthquakes' || !e.isSourceLoaded) return;

        map.on('move', updateMarkers);
        map.on('moveend', updateMarkers);
        updateMarkers();
    });

});

我尝试了这个但没有帮助。

map.on('click', 'states-layer', function (e) {
new mapboxgl.Popup()
.setLngLat(e.lngLat)
.setHTML(e.features[0].properties.name)
.addTo(map);
});

// Change the cursor to a pointer when the mouse is over the states layer.
map.on('mouseenter', 'states-layer', function () {
map.getCanvas().style.cursor = 'pointer';
});

// Change it back to a pointer when it leaves.
map.on('mouseleave', 'states-layer', function () {
map.getCanvas().style.cursor = '';
});

还尝试了marker.popup()函数。 任何帮助将不胜感激。

谢谢, 痛点

1 个答案:

答案 0 :(得分:0)

尽量不要创建标记。而是为地图中的单点制作一个图层。您可以将图标添加到图层,使其看起来像一个标记。它是这样的:

首先,您应该为未聚类的点添加图层。

带有图标的示例:

map.loadImage('https://imageURL', function(error, image) {
    if (error) throw error;
    map.addImage('IMAGE-NAME', image);

    map.addLayer({
        id: "unclustered-point",
        type: "symbol",
        source: "earthquakes",
        filter: ["!", ["has", "point_count"]],
        layout: {
            "icon-image": 'IMAGE-NAME',
            "icon-size":1,
            }
    });

不带图标的示例:

map.addLayer({
        id: "unclustered-point",
        type: "circle",
        source: "earthquakes",
        filter: ["!", ["has", "point_count"]],
    });

然后添加一个点击事件:

map.on('click', 'unclustered-point', function (e) {
    new mapboxgl.Popup()
    .setLngLat(e.lngLat)
    .setHTML(e.features[0].properties.description)
    .addTo(map);
    });

请记住将您的代码放入map.on(“ load” ...)函数中

map.on('load', function() 
{
  //put your code here
}

我认为,要使其正常运行,您不必使用自己的标记代码。