Compare commits
2 Commits
a846232e04
...
b8a617ed8d
| Author | SHA1 | Date | |
|---|---|---|---|
| b8a617ed8d | |||
| 8f22938c50 |
173
GEE_Scripts/LST_download.js
Normal file
173
GEE_Scripts/LST_download.js
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
/**
|
||||||
|
* Landsat 系列地表温度 (LST) 数据下载 —— 以年平均温度处理下载为例
|
||||||
|
*
|
||||||
|
* @author CVEO Team
|
||||||
|
* @date 2026-01-15
|
||||||
|
*
|
||||||
|
* 1. 加载 Landsat-8, Landsat-9 SR 数据
|
||||||
|
* 2. 合并 Landsat-8, Landsat-9 LST 数据
|
||||||
|
* 3. 合成年度平均 Landsat LST 数据
|
||||||
|
* 4. 导出 COG 云优化并填补缺失值的 GeoTIFF 影像 (大区域 GEE 自动分块下载)
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 加载研究区域和影像
|
||||||
|
var region_name = "应城市";
|
||||||
|
var region_name_en = "Yingcheng";
|
||||||
|
var region = Yingcheng;
|
||||||
|
var crs = "EPSG:4526";
|
||||||
|
// var region_name = "保康县";
|
||||||
|
// var region_name_en = "Baokang";
|
||||||
|
// var region = Baokang;
|
||||||
|
// var crs = "EPSG:4525";
|
||||||
|
var start_year = 2021;
|
||||||
|
var end_year = 2025;
|
||||||
|
var start_date = start_year + "-01-01";
|
||||||
|
var end_date = end_year + "-12-31";
|
||||||
|
var cloud_threshold = 90; // 最大云量阈值
|
||||||
|
var LansatBands = ["ST_B10"];
|
||||||
|
var commonBands = ["LST"];
|
||||||
|
|
||||||
|
var region_geo = region.geometry();
|
||||||
|
var bounds = region_geo.bounds();
|
||||||
|
var common_filter = ee.Filter.and(
|
||||||
|
ee.Filter.bounds(bounds),
|
||||||
|
ee.Filter.date(start_date, end_date)
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies scaling factors.
|
||||||
|
* @param {ee.Image} image Landsat SR image
|
||||||
|
* @returns {ee.Image} Landsat SR image with scaled bands
|
||||||
|
*/
|
||||||
|
function applyScaleFactors(image) {
|
||||||
|
var opticalBands = image.select("SR_B.").multiply(0.0000275).add(-0.2);
|
||||||
|
var thermalBands = image.select("ST_B.*").multiply(0.00341802).add(149.0);
|
||||||
|
return image
|
||||||
|
.addBands(opticalBands, null, true)
|
||||||
|
.addBands(thermalBands, null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开尔文转摄氏度
|
||||||
|
* @param {ee.Image} image Landsat LST image
|
||||||
|
* @returns {ee.Image} Landsat LST image in Celsius
|
||||||
|
*/
|
||||||
|
function kelvinToCelsius(image) {
|
||||||
|
return ee.Image(image.expression("B1 - 273.15", { B1: image.select(0) }))
|
||||||
|
.rename("LST")
|
||||||
|
.copyProperties(image)
|
||||||
|
.copyProperties(image, ["system:time_start", "system:index", "system:id"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to mask clouds using the Landsat QA_PIXEL and QA_RADSAT bands
|
||||||
|
* @param {ee.Image} image Landsat SR image
|
||||||
|
* @return {ee.Image} cloud masked and saturated Landsat SR image
|
||||||
|
*/
|
||||||
|
function maskLandsatclouds(image) {
|
||||||
|
var qa = image.select("QA_PIXEL");
|
||||||
|
var qa_radsat = image.select("QA_RADSAT");
|
||||||
|
// Bits 3 and 4 are cloud and cloud shadow, respectively.
|
||||||
|
var cloudBitMask = 1 << 3;
|
||||||
|
var shadowBitMask = 1 << 4;
|
||||||
|
// Both flags should be set to zero, indicating clear conditions.
|
||||||
|
var mask = qa.bitwiseAnd(cloudBitMask).eq(0)
|
||||||
|
.and(qa.bitwiseAnd(shadowBitMask).eq(0))
|
||||||
|
.and(qa_radsat.eq(0));
|
||||||
|
image = image.updateMask(mask);
|
||||||
|
return image
|
||||||
|
.copyProperties(image)
|
||||||
|
.copyProperties(image, ["system:time_start", "system:index", "system:id"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载 Landsat-8, Landsat-9 SR 数据
|
||||||
|
var L8dataset = ee.ImageCollection("LANDSAT/LC08/C02/T1_L2")
|
||||||
|
.filter(common_filter)
|
||||||
|
.filter(ee.Filter.lt("CLOUD_COVER", cloud_threshold));
|
||||||
|
print(start_date + " - " + end_date + " Landsat-8 SR dataset", L8dataset);
|
||||||
|
var L9dataset = ee.ImageCollection("LANDSAT/LC09/C02/T1_L2")
|
||||||
|
.filter(common_filter)
|
||||||
|
.filter(ee.Filter.lt("CLOUD_COVER", cloud_threshold));
|
||||||
|
print(start_date + " - " + end_date + " Landsat-9 SR dataset", L9dataset);
|
||||||
|
|
||||||
|
// 合并 Landsat-8, Landsat-9 LST 数据
|
||||||
|
var LSTdataset = L8dataset.merge(L9dataset)
|
||||||
|
.map(applyScaleFactors)
|
||||||
|
.map(maskLandsatclouds)
|
||||||
|
.select(LansatBands, commonBands)
|
||||||
|
.map(kelvinToCelsius);
|
||||||
|
print(start_date + " - " + end_date + " Landsat-8,9 LST dataset", LSTdataset);
|
||||||
|
|
||||||
|
// 合成年度平均 Landsat LST 数据
|
||||||
|
var years = ee.List.sequence(start_year, end_year);
|
||||||
|
var months = ee.List.sequence(1, 12);
|
||||||
|
var yearlyLST = ee.ImageCollection.fromImages(
|
||||||
|
years.map(function (y) {
|
||||||
|
return ee.ImageCollection.fromImages(
|
||||||
|
months.map(function (m) {
|
||||||
|
return LSTdataset
|
||||||
|
.filter(ee.Filter.calendarRange(y, y, "year"))
|
||||||
|
.filter(ee.Filter.calendarRange(m, m, "month"))
|
||||||
|
.mean()
|
||||||
|
.clip(bounds)
|
||||||
|
.set("month", m)
|
||||||
|
.set("year", y);
|
||||||
|
})
|
||||||
|
).mean().set("year", y);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
if (start_year == end_year) {
|
||||||
|
var year_str = start_year;
|
||||||
|
} else {
|
||||||
|
var year_str = start_year + "-" + end_year;
|
||||||
|
}
|
||||||
|
print(year_str + " Annual Mean Landsat LST dataset", yearlyLST);
|
||||||
|
|
||||||
|
var total_mean_LST = LSTdataset.select("LST").mean();
|
||||||
|
print(year_str + " Total Year Mean Landsat LST Histogram", ui.Chart.image.histogram(total_mean_LST, region, 100, 258));
|
||||||
|
|
||||||
|
var annual_mean_LST = yearlyLST.select("LST").mean();
|
||||||
|
print(year_str + " Annual Mean Landsat LST Histogram", ui.Chart.image.histogram(annual_mean_LST, region, 100, 258));
|
||||||
|
|
||||||
|
var lst_vis = {
|
||||||
|
min: 2,
|
||||||
|
max: 40,
|
||||||
|
palette: [
|
||||||
|
'040274', '040281', '0502a3', '0502b8', '0502ce', '0502e6',
|
||||||
|
'0602ff', '235cb1', '307ef3', '269db1', '30c8e2', '32d3ef',
|
||||||
|
'3be285', '3ff38f', '86e26f', '3ae237', 'b5e22e', 'd6e21f',
|
||||||
|
'fff705', 'ffd611', 'ffb613', 'ff8b13', 'ff6e08', 'ff500d',
|
||||||
|
'ff0000', 'de0101', 'c21301', 'a71001', '911003'
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
var styling = {
|
||||||
|
color: "blue",
|
||||||
|
fillColor: "00000000",
|
||||||
|
};
|
||||||
|
|
||||||
|
Map.centerObject(region, 10);
|
||||||
|
Map.addLayer(total_mean_LST, lst_vis, year_str + " Landsat Total Year Mean LST");
|
||||||
|
Map.addLayer(annual_mean_LST, lst_vis, year_str + " Landsat Annual Mean LST");
|
||||||
|
Map.addLayer(region.style(styling), {}, region_name);
|
||||||
|
|
||||||
|
// 导出合并后的影像
|
||||||
|
// 明确设置数据类型为Float32, 否则默认类型为Float64, 会占用更多内存
|
||||||
|
// 并对缺失值进行填充, 否则默认为nan不便于后续本地处理
|
||||||
|
var processed_img = annual_mean_LST.toFloat().unmask(-9999.0);
|
||||||
|
print("Start exporting " + year_str + "Yearly Mean LST image (" + crs + ")", processed_img);
|
||||||
|
Export.image.toDrive({
|
||||||
|
image: processed_img,
|
||||||
|
description: region_name_en + "_LST_" + year_str,
|
||||||
|
folder: "LST",
|
||||||
|
region: region, // 添加后会自动裁剪
|
||||||
|
scale: 30,
|
||||||
|
crs: crs,
|
||||||
|
maxPixels: 1e13, // GEE 最多支持 1e8 像素, 当超过时会自动分块
|
||||||
|
fileFormat: "GeoTIFF",
|
||||||
|
// 导出COG云优化的GeoTIFF影像, 并明确设置缺失值为-9999.0
|
||||||
|
formatOptions: {
|
||||||
|
cloudOptimized: true,
|
||||||
|
noData: -9999.0,
|
||||||
|
},
|
||||||
|
});
|
||||||
267
GEE_Scripts/LULC_download.js
Normal file
267
GEE_Scripts/LULC_download.js
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
/**
|
||||||
|
* 土地覆盖分类数据下载
|
||||||
|
*
|
||||||
|
* @author CVEO Team
|
||||||
|
* @date 2025-10-27
|
||||||
|
*
|
||||||
|
* 1. 加载 ESA WorldCover, Dynamic World 等公开土地覆盖数据
|
||||||
|
* - ESA WorldCover 2021 V200 版本: 11 类地物
|
||||||
|
* - Dynamic World V1 版本: 9 类地物
|
||||||
|
* 2. 加载 Sentinel-2 数据
|
||||||
|
* 3. 导出 COG 云优化并填补缺失值的 GeoTIFF 影像 (大区域 GEE 自动分块下载)
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 加载研究区域和影像
|
||||||
|
// var region_name = "武汉市";
|
||||||
|
// var region_name_en = "Wuhan";
|
||||||
|
// var region = allCites.filter(ee.Filter.eq("市", region_name));
|
||||||
|
var region_name = "49REL";
|
||||||
|
var region_name_en = region_name;
|
||||||
|
var region = grid;
|
||||||
|
var year = 2025;
|
||||||
|
var start_date = year + "-01-01";
|
||||||
|
var end_date = year + "-12-31";
|
||||||
|
var target_month = 5; // 指定月份
|
||||||
|
var cloud_threshold = 60;
|
||||||
|
// Use 'cs' or 'cs_cdf', depending on your use case; see docs for guidance.
|
||||||
|
var QA_BAND = "cs_cdf";
|
||||||
|
// The threshold for masking; values between 0.50 and 0.65 generally work well.
|
||||||
|
// Higher values will remove thin clouds, haze & cirrus shadows.
|
||||||
|
var CLEAR_THRESHOLD = 0.7;
|
||||||
|
// Sentinel-2的B8A波段(20m)可能更适合代表近红外波段
|
||||||
|
// var s2Bands = ["B2", "B3", "B4", "B8", "B11", "B12"];
|
||||||
|
var s2Bands = ["B2", "B3", "B4", "B8A", "B11", "B12"];
|
||||||
|
var commonBands = ["Blue", "Green", "Red", "NIR", "SWIR1", "SWIR2"];
|
||||||
|
var bounds = region.geometry().bounds();
|
||||||
|
var common_filter = ee.Filter.and(
|
||||||
|
ee.Filter.bounds(bounds),
|
||||||
|
ee.Filter.date(start_date, end_date)
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基于 Cloud Score+ 云掩膜
|
||||||
|
* @param {ee.Image} image Sentinel-2 image
|
||||||
|
* @return {ee.Image} cloud masked Sentinel-2 image
|
||||||
|
*/
|
||||||
|
function maskS2cloudsByCS(image) {
|
||||||
|
var cloudMask = image.select(QA_BAND).gte(CLEAR_THRESHOLD);
|
||||||
|
image = image.updateMask(cloudMask);
|
||||||
|
return image
|
||||||
|
.copyProperties(image)
|
||||||
|
.copyProperties(image, ["system:time_start", "system:index", "system:id"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按照属性值对影像集合进行排序
|
||||||
|
* @param {ee.ImageCollection} collection 影像集合
|
||||||
|
* @param {ee.Geometry} region 目标区域
|
||||||
|
* @return {ee.ImageCollection} 排序后的影像集合
|
||||||
|
*/
|
||||||
|
function sortedByPriority(collection, region) {
|
||||||
|
// 1. 计算每张影像的有效像素 (非空像素) 覆盖面积
|
||||||
|
var withArea = collection.map(function (image) {
|
||||||
|
var area = image
|
||||||
|
.mask()
|
||||||
|
.reduceRegion({
|
||||||
|
reducer: ee.Reducer.sum(),
|
||||||
|
geometry: region,
|
||||||
|
scale: 10,
|
||||||
|
maxPixels: 1e9,
|
||||||
|
})
|
||||||
|
.values()
|
||||||
|
.get(0);
|
||||||
|
return image.set("coverage_area", area);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. 剔除覆盖面积为 0 的影像
|
||||||
|
withArea = withArea.filter(ee.Filter.gt("coverage_area", 0));
|
||||||
|
|
||||||
|
// 3. 根据云量 (降序) 和覆盖率 (升序) 对影像进行综合排序
|
||||||
|
// 考虑影像集合是以栈的形式 (先入后出) 组织的, 在进行 mosaic 合成时, 从最后一张影像开始合并, 逆转排序
|
||||||
|
// sort 默认升序 True
|
||||||
|
var sorted = withArea
|
||||||
|
.sort("CLOUDY_PIXEL_PERCENTAGE", false)
|
||||||
|
.sort("coverage_area");
|
||||||
|
return ee.ImageCollection(sorted);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载Sentinel-2 L2A数据
|
||||||
|
// Cloud Score+ image collection.
|
||||||
|
// Note Cloud Score+ is produced from Sentinel-2 level 1C data and can be applied to either L1C or L2A collections.
|
||||||
|
var S2csPlus = ee.ImageCollection("GOOGLE/CLOUD_SCORE_PLUS/V1/S2_HARMONIZED");
|
||||||
|
var S2dataset = ee
|
||||||
|
.ImageCollection("COPERNICUS/S2_SR_HARMONIZED")
|
||||||
|
.filter(common_filter)
|
||||||
|
.filter(ee.Filter.lt("CLOUDY_PIXEL_PERCENTAGE", cloud_threshold))
|
||||||
|
.select(s2Bands, commonBands)
|
||||||
|
.linkCollection(S2csPlus, [QA_BAND])
|
||||||
|
.map(maskS2cloudsByCS);
|
||||||
|
var target_s2 = sortedByPriority(
|
||||||
|
S2dataset.filter(
|
||||||
|
ee.Filter.calendarRange(target_month, target_month, "month")
|
||||||
|
),
|
||||||
|
region
|
||||||
|
);
|
||||||
|
var s2_img = ee.Image(target_s2.median());
|
||||||
|
|
||||||
|
// 加载ESA WorldCover数据
|
||||||
|
var ESA_worldcover = ee.ImageCollection("ESA/WorldCover/v200").first();
|
||||||
|
var wc_img = ee.Image(ESA_worldcover.clip(region));
|
||||||
|
var wc_class_names = {
|
||||||
|
"Tree cover": 10,
|
||||||
|
Shrubland: 20,
|
||||||
|
Grassland: 30,
|
||||||
|
Cropland: 40,
|
||||||
|
"Built-up": 50,
|
||||||
|
"Bare / sparse vegetation": 60,
|
||||||
|
"Snow and ice": 70,
|
||||||
|
"Permanent water bodies": 80,
|
||||||
|
"Herbaceous wetland": 90,
|
||||||
|
Mangroves: 95,
|
||||||
|
"Moss and lichen": 100,
|
||||||
|
};
|
||||||
|
// 统计各类别覆盖面积
|
||||||
|
var wc_class_area = wc_img
|
||||||
|
.reduceRegion({
|
||||||
|
reducer: ee.Reducer.frequencyHistogram(),
|
||||||
|
geometry: region,
|
||||||
|
scale: 10,
|
||||||
|
maxPixels: 1e13,
|
||||||
|
})
|
||||||
|
.get("Map");
|
||||||
|
print("ESA WorldCover 2021 v200");
|
||||||
|
print("各类别名称:", wc_class_names);
|
||||||
|
print("各类别覆盖面积:", wc_class_area);
|
||||||
|
|
||||||
|
// 加载Dynamic World数据
|
||||||
|
var DWdataset = ee
|
||||||
|
.ImageCollection("GOOGLE/DYNAMICWORLD/V1")
|
||||||
|
.filter(common_filter)
|
||||||
|
.select("label");
|
||||||
|
// mode() 取出现次数最多的类别作为合成后的类别
|
||||||
|
var dw_img = ee.Image(DWdataset.mode().clip(region));
|
||||||
|
var dw_class_names = {
|
||||||
|
water: 0,
|
||||||
|
trees: 1,
|
||||||
|
grass: 2,
|
||||||
|
flooded_vegetation: 3,
|
||||||
|
crops: 4,
|
||||||
|
shrub_and_scrub: 5,
|
||||||
|
built: 6,
|
||||||
|
bare: 7,
|
||||||
|
snow_and_ice: 8,
|
||||||
|
};
|
||||||
|
var built_img = dw_img.updateMask(dw_img.eq(dw_class_names.built));
|
||||||
|
var crop_img = dw_img.updateMask(dw_img.eq(dw_class_names.crops));
|
||||||
|
var flood_img = dw_img.updateMask(dw_img.eq(dw_class_names.flooded_vegetation));
|
||||||
|
// 统计各类别覆盖面积
|
||||||
|
var dw_class_area = dw_img
|
||||||
|
.reduceRegion({
|
||||||
|
reducer: ee.Reducer.frequencyHistogram(),
|
||||||
|
geometry: region,
|
||||||
|
scale: 10,
|
||||||
|
maxPixels: 1e13,
|
||||||
|
})
|
||||||
|
.get("label");
|
||||||
|
print("Dynamic World v1");
|
||||||
|
print("各类别名称:", dw_class_names);
|
||||||
|
print("各类别覆盖面积:", dw_class_area);
|
||||||
|
|
||||||
|
var VIS_PALETTE = [
|
||||||
|
"419bdf",
|
||||||
|
"397d49",
|
||||||
|
"88b053",
|
||||||
|
"7a87c6",
|
||||||
|
"e49635",
|
||||||
|
"dfc35a",
|
||||||
|
"c4281b",
|
||||||
|
"a59b8f",
|
||||||
|
"b39fe1",
|
||||||
|
];
|
||||||
|
var DW_vis = {
|
||||||
|
min: 0,
|
||||||
|
max: 8,
|
||||||
|
palette: VIS_PALETTE,
|
||||||
|
};
|
||||||
|
|
||||||
|
var true_rgb_vis = {
|
||||||
|
bands: ["Red", "Green", "Blue"],
|
||||||
|
min: 0.0,
|
||||||
|
max: 3000,
|
||||||
|
};
|
||||||
|
|
||||||
|
var false_rgb_vis = {
|
||||||
|
min: 0.0,
|
||||||
|
max: 4000,
|
||||||
|
gamma: 1.4,
|
||||||
|
bands: ["NIR", "Red", "Green"],
|
||||||
|
};
|
||||||
|
|
||||||
|
var styling = {
|
||||||
|
color: "red",
|
||||||
|
fillColor: "00000000",
|
||||||
|
};
|
||||||
|
|
||||||
|
var WC_vis = {
|
||||||
|
bands: ["Map"],
|
||||||
|
};
|
||||||
|
|
||||||
|
Map.centerObject(region, 9);
|
||||||
|
Map.addLayer(region.style(styling), {}, region_name);
|
||||||
|
Map.addLayer(wc_img, WC_vis, "ESA 2021 Landcover");
|
||||||
|
Map.addLayer(dw_img, DW_vis, "Dynamic World LULC");
|
||||||
|
Map.addLayer(
|
||||||
|
s2_img,
|
||||||
|
true_rgb_vis,
|
||||||
|
year + "-" + target_month + " Sentinel-2 True RGB",
|
||||||
|
false
|
||||||
|
);
|
||||||
|
Map.addLayer(
|
||||||
|
s2_img,
|
||||||
|
false_rgb_vis,
|
||||||
|
year + "-" + target_month + " Sentinel-2 False RGB",
|
||||||
|
false
|
||||||
|
);
|
||||||
|
// Map.addLayer(built_img, DW_vis, 'Built DW LULC');
|
||||||
|
// Map.addLayer(crop_img, DW_vis, "Crop DW LULC");
|
||||||
|
// Map.addLayer(flood_img, DW_vis, "Flood DW LULC");
|
||||||
|
|
||||||
|
// 导出裁剪处理后的土地覆盖数据
|
||||||
|
var fileName = region_name_en + "_ESA_WorldCover_2021_v200";
|
||||||
|
// 区域过大, 需要先将 wc_img 划分为四块网格分开下载
|
||||||
|
var bounds = region.geometry().bounds();
|
||||||
|
var coords = ee.List(bounds.coordinates().get(0));
|
||||||
|
|
||||||
|
var minX = ee.Number(ee.List(coords.get(0)).get(0));
|
||||||
|
var minY = ee.Number(ee.List(coords.get(0)).get(1));
|
||||||
|
var maxX = ee.Number(ee.List(coords.get(2)).get(0));
|
||||||
|
var maxY = ee.Number(ee.List(coords.get(2)).get(1));
|
||||||
|
|
||||||
|
var midX = minX.add(maxX).divide(2);
|
||||||
|
var midY = minY.add(maxY).divide(2);
|
||||||
|
|
||||||
|
var grid1 = ee.Geometry.Rectangle([minX, minY, midX, midY]);
|
||||||
|
var grid2 = ee.Geometry.Rectangle([midX, minY, maxX, midY]);
|
||||||
|
var grid3 = ee.Geometry.Rectangle([minX, midY, midX, maxY]);
|
||||||
|
var grid4 = ee.Geometry.Rectangle([midX, midY, maxX, maxY]);
|
||||||
|
|
||||||
|
var grids = [grid1, grid2, grid3, grid4];
|
||||||
|
|
||||||
|
for (var i = 0; i < grids.length; i++) {
|
||||||
|
var grid_region = grids[i];
|
||||||
|
var clipped_img = wc_img.clip(grid_region);
|
||||||
|
var grid_fileName = fileName + "_grid_" + (i + 1);
|
||||||
|
Export.image.toDrive({
|
||||||
|
image: clipped_img,
|
||||||
|
description: grid_fileName,
|
||||||
|
folder: "LULC",
|
||||||
|
region: grid_region,
|
||||||
|
scale: 10,
|
||||||
|
maxPixels: 1e13, // GEE 最多支持 1e8 像素, 当超过时会自动分块
|
||||||
|
fileFormat: "GeoTIFF",
|
||||||
|
// 导出COG云优化的GeoTIFF影像
|
||||||
|
formatOptions: {
|
||||||
|
cloudOptimized: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user