将源添加到地图框GL

时间:2016-09-05 17:01:00

标签: asynchronous firebase-realtime-database 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中的地图异步添加标记。

2 个答案:

答案 0 :(得分:3)

我有同样的问题。我做了一些搜索,我找到了GeoJSONSource的setData属性: https://www.mapbox.com/mapbox-gl-js/api/#geojsonsource#setdata

AbstractAlgorithm foo = new AbstractAlgorithm();
foo.makeDecision(new Decision<StringData>());   // OK.
foo.makeDecision(new Decision<IntegerData>());  // OK.

然后我更新源代码,而不创建像这样的新图层:

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) 删除了所有以前的数据(没有&#34; addData&#34;功能),因此您需要保存以前的标记并再次添加它们。如果您找到解决方法,请告诉我。

答案 1 :(得分:1)

正如https://www.mapbox.com/mapbox-gl-js/api/#geojsonsource所述的文档:GeoJSON数据对象或一个URL。对于大型GeoJSON文件,后者更可取。

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

此外,Leaflet的创始人和惊人的Mapbox开发人员Vladimir Agafonkin在此讨论了这个问题:https://github.com/mapbox/mapbox-gl-js/issues/2289,它实际上就是他们在实时示例中所做的: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}"
                }
            });
        });