Asynchronous 将源添加到mapbox GL中的现有图层
这个标题几乎说明了我打算做什么 我使用Firebase作为地图上标记的后端,并使用('child_added')方法监视这些标记。对于数据库中特定位置上的每个节点,on('child_added')将触发一次 这也适用于正在创建的新节点,因此这非常适合在将新标记添加到数据库时将其异步添加到地图 为了在地图上显示这些,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
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}"
}
});
});