将源添加到 mapbox GL 中的现有层

Add source to existing layer in mapbox GL

标题几乎说明了我打算做什么。

我使用 Firebase 作为地图上标记的后端,并使用 on('child_added') 方法来监控这些标记。对于数据库中特定位置上的每个节点,on('child_added') 将触发一次。

这也适用于正在创建的新节点,因此这非常适合在将新标记添加到数据库时将它们异步添加到地图。

为了在地图上显示这些,mapbox GL 要求我将数据转换为 geojson,创建一个源,然后将此源添加到图层。下面的代码显示了这一点,它实际上显示了地图上的标记。

markersRef.on('child_added', function(childSnapshot) { //fires once for every child node
    var currentKey = childSnapshot.key; //the key of current child
    var entry = childSnapshot.val(); //the value of current child

    //creates a geojson object from child
    var geojson = {
        "type": "FeatureCollection",
        "features": [{
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [entry.position.long, entry.position.lat]
            }
        }],
        "properties": {
            title: entry.title,
            text: entry.text
        }
    };

    //creates a source with the geojson object from above
    map.addSource(currentKey, { //currentKey is the name of this source
        "type": "geojson",
        "data": geojson,
        cluster: true //clusters the points in this source
    });

    //adds the source defined above to a layer that will be displayed on a map
    map.addLayer({
        "id": currentKey, // Sets id as current child's key 
        "source": currentKey, // The source layer defined above
    });
});

问题在于标记将位于不同的源中,从而使它们出现在不同的图层上。因此,我不能将它们聚类,或者例如搜索它们。

我寻找的是一种将源添加到现有层的方法。这将使我能够在 on('child_added') 方法之外创建一个层,然后将源添加到该层。

我查看了 mapbox GL 文档,但我在其中找不到任何可以让我执行此操作的内容。和mapbox js相比,在这方面似乎很有限

我认为这是一个非常重要的功能,但不明白为什么这是不可能的。我希望你们中的一些人有解决方法或方法来实现在 mapbox GL 中向地图异步添加标记。

我也遇到了同样的问题。我对此进行了一些搜索,并找到了 GeoJSONSource 的 setData 属性: https://www.mapbox.com/mapbox-gl-js/api/#geojsonsource#setdata

map.addSource("points", markers);
map.addLayer({
  "id": "points",
  "type": "symbol",
  "source": "points",
  "layout": {
  "icon-image": "{icon}-15",
  "icon-allow-overlap": true,
  "icon-ignore-placement": true,
  "icon-size": 2,
  "icon-offset": [0, -10],
  }
});

然后我更新源代码,而不是像这样创建一个新层:

map.getSource('points').setData(newMarkers)

因此,这会在不创建新层的情况下更新源。然后你可以搜索这一层。我遇到的唯一问题是 setData 删除了所有以前的数据(没有 "addData" 功能)所以你需要保存以前的标记并重新添加它们。如果您找到解决方法,请告诉我。

https://www.mapbox.com/mapbox-gl-js/api/#geojsonsource 处的文档所述:地理 JSON 数据对象或 URL 到一个。在大型 GeoJSON 文件的情况下,后者更可取。

这里发生的是,通过 url 加载的 geojson 源是使用后台线程工作者加载的,因此它们不会影响主线程,基本上总是通过 url 或 mapbox 加载数据样式将所有 JSON 解析和层加载卸载到另一个线程。因此,只要您从 firebase 监控中触发了更改事件,您就可以简单地重新加载您用于初始加载源的 url。

此外,Leaflet 的创始人和出色的 Mapbox 开发人员 Vladimir Agafonkin 在这里讨论了这个问题:https://github.com/mapbox/mapbox-gl-js/issues/2289, and it is essentially what they do in their real-time example: https://www.mapbox.com/mapbox-gl-js/example/live-geojson/

此外,这里有一个 socket.io 我使用客户端的例子:

const url = {server url that retrieves geojson},
      socket = {setup all your socket initiation, etc};

      socket.on('msg', function(data) {

            if (data) {
                //Here is where you can manipulate the JSON object returned from the socket server
                console.log("Message received is: %s", JSON.stringify(data));
                if(data.fetch){
                    map.getSource('stuff').setData(url)
                }

            } else {
                console.log("Message received is empty: so it is %s", JSON.stringify(data));
            }

        });


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

            map.addSource('events', {
                type: 'stuff',
                data: url
            });
            map.addLayer({
                "id": "events",
                "type": "symbol",
                "source": "events",
                "layout": {
                    "icon-image": "{icon}"
                }
            });
        });