Javascript 闭包:如何将动态底层添加到 Cesium 地图
Javascript closure: How to add dynamic baselayers to Cesium map
我正在尝试从数据库中的一组值向 Cesium 地图添加多个基础层。我希望 javascript 只是遍历它们然后添加它们。这是来自 Cesium 的静态代码示例:
var imageryViewModels = [];
imageryViewModels.push(new Cesium.ProviderViewModel({
name : 'Open\u00adStreet\u00adMap',
iconUrl : Cesium.buildModuleUrl('openStreetMap.png'),
tooltip : 'OpenStreetMap (OSM)',
creationFunction : function() {
return Cesium.createOpenStreetMapImageryProvider({
url : 'https://a.tile.openstreetmap.org/'
});
}
}));
imageryViewModels.push(new Cesium.ProviderViewModel({
name : 'Black Marble',
iconUrl : Cesium.buildModuleUrl('blackMarble.png'),
tooltip : 'outlines of civilization',
creationFunction : function() {
return Cesium.createTileMapServiceImageryProvider({
url : 'https://cesiumjs.org/blackmarble',
credit : 'B Observatory',
flipXY : true
});
}
}));
到目前为止,使用一组静态值非常简单。这就是它变得棘手的地方,我想遍历一组值,然后将 ProviderViewModels 推送到数组。像这样 -
var imageryViewModels = [];
baseLayers = HashOfValuesFromDatabase;
for(int i=0; i<baseLayers.length; i++{
imageryViewModels.push(new Cesium.ProviderViewModel({
name : baseLayers[i].name,
iconUrl : Cesium.buildModuleUrl(baseLayers[i].iconUrl),
tooltip : baseLayser[i].toolTip,
creationFunction : function() {
return Cesium.createOpenStreetMapImageryProvider({
url : baseLayers[i].url // ***** this value always the last value ****
});
}
}));
}
问题是 javascript 闭包给我带来了问题,我的每一个 imageryViewModels 都是 baseLayer.url 对象中的最后一个值。 Cesium 需要 this 在这里成为一个函数。有没有办法让这个函数保持不变,但得到迭代的值 baseLayer.url?
请试试这个(我没有运行):
var imageryViewModels = [];
baseLayers = HashOfValuesFromDatabase;
for(int i=0; i<baseLayers.length; i++{
imageryViewModels.push(new Cesium.ProviderViewModel({
name : baseLayers[i].name,
iconUrl : Cesium.buildModuleUrl(baseLayers[i].iconUrl),
tooltip : baseLayser[i].toolTip,
creationFunction : (function(i) {
return function() {
return Cesium.createOpenStreetMapImageryProvider({
url : baseLayers[i].url
});
}
}(i))
}));
}
编辑:语法正确(感谢 emackey)
Ben Aston 的回答是这里的正确方法。他没有尝试 运行ning 它,并且在 }(i))
之后有一个额外的分号在参数列表中是非法的,而且他还从您的原始问题中复制粘贴了一些问题。这是更正后的版本,我确实得到了 运行:
var imageryViewModels = [];
for(var i=0; i<baseLayers.length; i++) {
imageryViewModels.push(new Cesium.ProviderViewModel({
name : baseLayers[i].name,
iconUrl : Cesium.buildModuleUrl(baseLayers[i].iconUrl),
tooltip : baseLayers[i].toolTip,
creationFunction : (function(i) {
return function() {
return Cesium.createOpenStreetMapImageryProvider({
url : baseLayers[i].url
});
};
}(i))
}));
}
修复 url
参数的原因是因为 IIFE(立即调用的函数表达式)使用 i
作为参数。这会在循环中的每次迭代中创建一个新的 JavaScript 闭包,这很昂贵,但这是必需的,以便每个单独的 create
函数都有自己的闭包,并具有自己的 [=13= 值副本] 来自循环的特定迭代。没有这个,只有一个闭包只有一个 i
变量,并且当任何一个创建函数被实际调用时,循环早就完成了并且 i
的值已经达到最大值.
我正在尝试从数据库中的一组值向 Cesium 地图添加多个基础层。我希望 javascript 只是遍历它们然后添加它们。这是来自 Cesium 的静态代码示例:
var imageryViewModels = [];
imageryViewModels.push(new Cesium.ProviderViewModel({
name : 'Open\u00adStreet\u00adMap',
iconUrl : Cesium.buildModuleUrl('openStreetMap.png'),
tooltip : 'OpenStreetMap (OSM)',
creationFunction : function() {
return Cesium.createOpenStreetMapImageryProvider({
url : 'https://a.tile.openstreetmap.org/'
});
}
}));
imageryViewModels.push(new Cesium.ProviderViewModel({
name : 'Black Marble',
iconUrl : Cesium.buildModuleUrl('blackMarble.png'),
tooltip : 'outlines of civilization',
creationFunction : function() {
return Cesium.createTileMapServiceImageryProvider({
url : 'https://cesiumjs.org/blackmarble',
credit : 'B Observatory',
flipXY : true
});
}
}));
到目前为止,使用一组静态值非常简单。这就是它变得棘手的地方,我想遍历一组值,然后将 ProviderViewModels 推送到数组。像这样 -
var imageryViewModels = [];
baseLayers = HashOfValuesFromDatabase;
for(int i=0; i<baseLayers.length; i++{
imageryViewModels.push(new Cesium.ProviderViewModel({
name : baseLayers[i].name,
iconUrl : Cesium.buildModuleUrl(baseLayers[i].iconUrl),
tooltip : baseLayser[i].toolTip,
creationFunction : function() {
return Cesium.createOpenStreetMapImageryProvider({
url : baseLayers[i].url // ***** this value always the last value ****
});
}
}));
}
问题是 javascript 闭包给我带来了问题,我的每一个 imageryViewModels 都是 baseLayer.url 对象中的最后一个值。 Cesium 需要 this 在这里成为一个函数。有没有办法让这个函数保持不变,但得到迭代的值 baseLayer.url?
请试试这个(我没有运行):
var imageryViewModels = [];
baseLayers = HashOfValuesFromDatabase;
for(int i=0; i<baseLayers.length; i++{
imageryViewModels.push(new Cesium.ProviderViewModel({
name : baseLayers[i].name,
iconUrl : Cesium.buildModuleUrl(baseLayers[i].iconUrl),
tooltip : baseLayser[i].toolTip,
creationFunction : (function(i) {
return function() {
return Cesium.createOpenStreetMapImageryProvider({
url : baseLayers[i].url
});
}
}(i))
}));
}
编辑:语法正确(感谢 emackey)
Ben Aston 的回答是这里的正确方法。他没有尝试 运行ning 它,并且在 }(i))
之后有一个额外的分号在参数列表中是非法的,而且他还从您的原始问题中复制粘贴了一些问题。这是更正后的版本,我确实得到了 运行:
var imageryViewModels = [];
for(var i=0; i<baseLayers.length; i++) {
imageryViewModels.push(new Cesium.ProviderViewModel({
name : baseLayers[i].name,
iconUrl : Cesium.buildModuleUrl(baseLayers[i].iconUrl),
tooltip : baseLayers[i].toolTip,
creationFunction : (function(i) {
return function() {
return Cesium.createOpenStreetMapImageryProvider({
url : baseLayers[i].url
});
};
}(i))
}));
}
修复 url
参数的原因是因为 IIFE(立即调用的函数表达式)使用 i
作为参数。这会在循环中的每次迭代中创建一个新的 JavaScript 闭包,这很昂贵,但这是必需的,以便每个单独的 create
函数都有自己的闭包,并具有自己的 [=13= 值副本] 来自循环的特定迭代。没有这个,只有一个闭包只有一个 i
变量,并且当任何一个创建函数被实际调用时,循环早就完成了并且 i
的值已经达到最大值.