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

Asynchronous 将源添加到mapbox GL中的现有图层,asynchronous,firebase-realtime-database,mapbox-gl,Asynchronous,Firebase Realtime Database,Mapbox Gl,这个标题几乎说明了我打算做什么 我使用Firebase作为地图上标记的后端,并使用('child_added')方法监视这些标记。对于数据库中特定位置上的每个节点,on('child_added')将触发一次 这也适用于正在创建的新节点,因此这非常适合在将新标记添加到数据库时将其异步添加到地图 为了在地图上显示这些,mapbox GL要求我将数据转换为geojson,创建一个源,然后将该源添加到图层。下面的代码显示了这一点,它实际上显示了地图上的标记 markersRef.on('child_a

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

我使用Firebase作为地图上标记的后端,并使用('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
    });
});
问题是标记将出现在单独的源中,使它们出现在不同的层上。因此,我无法对它们进行聚类或搜索

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

我已经查看了mapbox GL文档,但在其中找不到任何可以让我这样做的内容。与mapbox js相比,它在这方面似乎非常有限


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

我也有同样的问题。我对此进行了一些搜索,找到了GeoJSONSource的setData属性:

然后,稍后我更新源,而不创建新层,如下所示:

map.getSource('points').setData(newMarkers)
因此,这将在不创建新层的情况下更新源。然后你可以在这个图层上搜索。我遇到的唯一问题是
setData
会擦除所有以前的数据(没有“addData”功能),因此需要保存以前的标记并再次添加它们。如果您找到了解决方法,请告诉我。

如states的文档所示:GeoJSON数据对象或指向该对象的URL。对于大型GeoJSON文件,后者更可取

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

此外,传单的创始人和惊人的地图盒开发者弗拉基米尔·阿加方金(Vladimir Agafonkin)在这里讨论了这一点:,这基本上就是他们在实时示例中所做的

此外,下面是我使用客户端的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}"
                }
            });
        });

嗯,我相信这是目前最好的解决办法。我最终联系了Mapbox,这实际上也是他们的建议。我想它是可行的,但我相信它一定是非常低效的,尤其是在数据集较大的情况下。无论如何,谢谢你的回复!如果我找到另一个解决方案,我会随时通知你-请做同样的事情:)我似乎记得在某个地方读到mapboxGL自动将新数据与以前的数据区分开来,并只更新必要的数据。。。
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}"
                }
            });
        });