【问题标题】:Mapbox GL Js - source.setData can't be seen in querySourceFeaturesMapbox GL Js - 在querySourceFeatures中看不到source.setData
【发布时间】:2020-04-16 12:14:30
【问题描述】:

我正在使用 mapbox 来绘制标记和集群,为此我正在使用 querySourceFeatures (https://docs.mapbox.com/mapbox-gl-js/api/#map#querysourcefeatures)。

我的设置基于 Mapbox (https://docs.mapbox.com/mapbox-gl-js/example/cluster-html/) 的博文

但是在我更新我的源(使用setData)后,querySourceFeatures 没有更新,所以我看不到我的新数据显示在地图上。

这是我的代码,有点简化:

const createData = (  ) => {
        markersToGenerate += 10;

        const totalFeatures = [{ "type": "Feature", "properties": { "id": "ak16994521", "mag": 2.3, "time": 1507425650893, "felt": null, "tsunami": 0 }, "geometry": { "type": "Point", "coordinates": [ -151.5129, 63.1016, 0.0 ] } }, 
 /** repeat this for 1200 times **/
];

        const splicedFeatures = totalFeatures.splice(0, markersToGenerate);

        return {
            'type': 'geojson',
            'data': {
                "type": "FeatureCollection",
                "crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
                "features": splicedFeatures
            },
            'cluster': true,
            'clusterRadius': 80,
            'clusterProperties': {
                // keep separate counts for each magnitude category in a cluster
                'mag1': ['+', ['case', mag1, 1, 0]],
                'mag2': ['+', ['case', mag2, 1, 0]],
                'mag3': ['+', ['case', mag3, 1, 0]],
                'mag4': ['+', ['case', mag4, 1, 0]],
                'mag5': ['+', ['case', mag5, 1, 0]]
            }
        }
    }

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

        // add a clustered GeoJSON source for a sample set of earthquakes
        map.addSource('earthquakes', createData());

        // circle and symbol layers for rendering individual earthquakes (unclustered points)

map.addLayer({
            'id': 'earthquake_circle',
            'type': 'circle',
            'source': 'earthquakes',
            'filter': ['!=', 'cluster', true],
            'paint': {
                'circle-color': [
                    'case',
                    mag1,
                    colors[0],
                    mag2,
                    colors[1],
                    mag3,
                    colors[2],
                    mag4,
                    colors[3],
                    colors[4]
                ],
                'circle-opacity': 0.6,
                'circle-radius': 12
            }
        });
        map.addLayer({
            'id': 'earthquake_label',
            'type': 'symbol',
            'source': 'earthquakes',
            'filter': ['!=', 'cluster', true],
            'layout': {
                'text-field': [
                    'number-format',
                    ['get', 'mag'],
                    { 'min-fraction-digits': 1, 'max-fraction-digits': 1 }
                ],
                'text-font': ['Open Sans Semibold', 'Arial Unicode MS Bold'],
                'text-size': 10
            },
            'paint': {
                'text-color': [
                    'case',
                    ['<', ['get', 'mag'], 3],
                    'black',
                    'white'
                ]
            }
        });

        // every 5 seconds add a marker to the source and set that
        setInterval( () => {
            console.log('Update source');

            map.getSource('earthquakes').setData(createData());
        }, 5000)

        // objects for caching and keeping track of HTML marker objects (for performance)
        var markers = {};
        var markersOnScreen = {};

        function updateMarkers() {
            console.log("# updateMarkers called")

            var features = map.querySourceFeatures('earthquakes');

            // There are more features retrieved - since some are displayed on multiple tiles ... so they are counted double. The point here is to show the count isn't increasing.

console.log("Total features displayed = " + features.reduce( (totalCount, feature) => {
                if (feature.properties.cluster) {
                    return totalCount + feature.properties.point_count;
                } else {
                    return totalCount + 1;
                }
            }, 0));
      }

如需完整(实际运行)代码,请查看此代码笔:https://codepen.io/skarnl/pen/RwWrdPm?editors=0010

一些额外的解释,我是如何测试这个的:

我添加了一个名为 createData 的方法,它将生成一个新的 GeoJson 并将其用于 setData 调用。我还添加了一个 setInterval 以每 5 秒添加 10 个标记。

我可以让这个工作的唯一方法是删除 both 源并再次重新添加它们。这行得通...但它会导致闪烁,因为该层已被完全删除。

我在这里做错了什么?

【问题讨论】:

    标签: javascript mapbox mapbox-gl-js


    【解决方案1】:

    在求助于 Mapbox GL JS 的官方 Gitlab 将其发布为错误后,解决方案变得非常简单:使用 setData 只需要获取 GeoJSON 的数据部分 - 而不是完整的 GeoJson 对象重新来过。

    所以只有设置数据才能解决这个问题。希望其他人可以使用此信息。

    用我自己的例子:

       map.getSource('earthquakes').setData(createData().data); 
    
       // The .data part is important here!
       // We don't want to use the complete GeoJSON, but only the data part in it
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-12
      • 2016-01-12
      • 2017-01-26
      • 2016-06-05
      • 2017-04-24
      • 2020-07-17
      • 2022-11-17
      • 1970-01-01
      相关资源
      最近更新 更多