将源添加到 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}"
}
});
});
标题几乎说明了我打算做什么。
我使用 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}"
}
});
});