在 Cesium.js 中使用 GeoJsonDataSource 加载更新数据

Loading updated data with GeoJsonDataSource in Cesium.js

我正在尝试将 Cesium 1.11 与现有后端发送 GeoJSON 集成。我能够从第一条消息成功地将数据加载到视图中,但是对 load() 的后续调用不会更新显示。

我已将问题简化为以下内容,也可作为 fiddle 使用。

代码

var viewer = new Cesium.Viewer('cesiumContainer');
var source = new Cesium.GeoJsonDataSource("name123");
viewer.dataSources.add(source);

source.load({
    type: "FeatureCollection",
    crs: {
        type: "name",
        properties: {
            name: "urn:ogc:def:crs:OGC:1.3:CRS84"
        }
    },
    features: [{
        type: "Feature",
        properties: {
            foo: 123,
        },
        geometry: {
            type: "Point",
            coordinates: [0.1275, 51.5072] // London
        },
        id: "123"
    }]
});

// workaround, but has side effect of destroying feature window
// source.entities.removeAll();

// sometime later...
source.load({
    type: "FeatureCollection",
    crs: {
        type: "name",
        properties: {
            name: "urn:ogc:def:crs:OGC:1.3:CRS84"
        }
    },
    features: [{
        type: "Feature",
        properties: {
            foo: 456,
        },
        geometry: {
            type: "Point",
            coordinates: [-75.1890, 42.3482] // New York
        },
        id: "123"
    }]
});

我试过的

更新:进一步调试。这个问题似乎是一个设计特征...

这看起来像是 Cesium 中的错误我刚刚提交了问题 #2891 and will try and get a fix into the 1.12 release on August 3rd. In the meantime, you should be able to workaround the issue using your removeAll strategy combined with resetting the selected entity after the load (which should keep the InfoBox around, which is what I assume you mean by feature window.) Here's a complete example that you can based into Sandcastle 以查看它的实际效果。

var viewer = new Cesium.Viewer('cesiumContainer');
var source = new Cesium.GeoJsonDataSource("name123");
viewer.dataSources.add(source);

Sandcastle.addToolbarButton('Load 1', function(){
    source.entities.removeAll();
    source.load({
        type: "FeatureCollection",
        crs: {
            type: "name",
            properties: {
                name: "urn:ogc:def:crs:OGC:1.3:CRS84"
            }
        },
        features: [{
            type: "Feature",
            properties: {
                foo: 123
            },
            geometry: {
                type: "Point",
                coordinates: [0.1275, 51.5072] // London
            },
            id: "123"
        }]
    }).then(function(){
        viewer.selectedEntity = source.entities.values[0];
    });
});

Sandcastle.addToolbarButton('Load 2', function() {
    source.entities.removeAll();
    source.load({
        type: "FeatureCollection",
        crs: {
            type: "name",
            properties: {
                name: "urn:ogc:def:crs:OGC:1.3:CRS84"
            }
        },
        features: [{
            type: "Feature",
            properties: {
                foo: 456
            },
            geometry: {
                type: "Point",
                coordinates: [-75.1890, 42.3482] // New York
            },
            id: "123"
        }]
    }).then(function(){
        viewer.selectedEntity = source.entities.values[0];
    });
});

另一种解决方案是仅使用 GeoJsonDataSource 从 JSON 创建实体,然后将 adding/updating 手动添加到查看器全局实体集合

var viewer = new Cesium.Viewer('cesiumContainer');
var source = new Cesium.GeoJsonDataSource("name123");
// don't add source to viewer

source.load(...);

// sometime later...
source.load(...);

// manually update
viewer.entities.suspendEvents();
source.entities.values.forEach(function(entity) {
    var existing = viewer.entities.getById(entity.id);
    if (existing === undefined) {
        viewer.entities.add(entity);
    } else {
        entity.propertyNames.forEach(function(name) {
            existing[name] = entity[name];  
        });
    }
}, this);
viewer.entities.resumeEvents();