六、添加可视化选择器(选择可视化的图像类型)
在前面的示例中,我们已经看到了同一Sentinel-2图像的真彩色合成、假彩色合成和NDVI渲染。如果能让用户从这些可视化中选择一个或更多,而不必每次都更改我们的代码,那就太好了。为此,我们将创建一个可用可视化的列表,并在页面中添加一个 <select>
元素,让用户选择要显示的内容。
除了真彩色、假彩色和NDVI可视化之外,我们还将添加一个新的归一化差异水指数(NDWI)。这与归一化差异植被指数类似,不同之处在于它可用于监测水体的变化。
js
NDWI = (GREEN - NIR) / (GREEN + NIR)
正如我们所看到的,每个可视化都需要有一个 sources
数组(这些是单波段或多波段GeoTIFF的URL),一个可选的 max
值用于缩放GeoTIFF值,一个可选的 style
用于渲染图层。此外,我们将为每个可视化提供给予一个 name
,以便显示给用户。
编辑您的 main.js
以包含以下可视化数据:
js
const visualizations = [
{
name: 'True Color',
sources: ['TCI'],
},
{
name: 'False Color',
sources: ['B08', 'B04', 'B03'],
max: 5000,
},
{
name: 'NDVI',
sources: ['B04', 'B08'],
max: 10000,
style: {
color: [
'interpolate',
['linear'],
['/', ['-', ['band', 2], ['band', 1]], ['+', ['band', 2], ['band', 1]]],
...getColorStops('earth', -0.5, 1, 10, true),
],
},
},
{
name: 'NDWI',
sources: ['B03', 'B08'],
max: 10000,
style: {
color: [
'interpolate',
['linear'],
['/', ['-', ['band', 1], ['band', 2]], ['+', ['band', 1], ['band', 2]]],
...getColorStops('viridis', -1, 1, 10, true),
],
},
},
];
现在,我们需要一个函数来在用户选择可视化时创建这些,而不是一次性创建GeoTIFF源和层。这个函数将接受一个 base
URL和一个 visualization
,并返回一个 layer
。编辑您的 main.js
以删除源和层定义,并包含此函数:
js
function createLayer(base, visualization) {
const source = new GeoTIFF({
//使用map函数遍历可视化配置中的每个数据源ID
sources: visualization.sources.map((id) => ({
url: `${base}/${id}.tif`,
max: visualization.max,
})),
});
return new TileLayer({
source: source,
style: visualization.style,
});
}
接下来,我们可以更改 main.js
中的地图定义,使其根本不包含任何图层(这些图层将在用户选择可视化时添加):
js
const map = new Map({
target: 'map-container',
});
现在,我们需要一种方法来让用户选择要显示的可视化。为此,我们将在 <script>
标记之前的 index.html
中添加一个 <select>
元素:
js
<div id="controls">
<select id="visualization"></select>
</div>
要让这个 <select>
元素显示在地图的右上角,请将以下块添加到 index.html
中的 <style>
标签:
js
#controls {
position: absolute;
top: 20px;
right: 20px;
}
有了 <select>
元素,我们需要为每个可视化名称填充一个 <option>
。要做到这一点,请将以下内容添加到 main.js
数组下面的某个位置:
js
const visualizationSelector = document.getElementById('visualization');
visualizations.forEach((visualization) => {
const option = document.createElement('option');
option.textContent = visualization.name;
visualizationSelector.appendChild(option);
});
最后,我们将创建一个函数,根据选定的可视化使用新层更新地图。我们将在 <select>
元素上添加这个函数作为 change
侦听器,并调用它来初始化我们的应用:
js
function updateVisualization() {
const visualization = visualizations[visualizationSelector.selectedIndex];
const base =
'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/21/H/UB/2021/9/S2B_21HUB_20210915_0_L2A';
const layer = createLayer(base, visualization);
map.setLayers([layer]);
}
visualizationSelector.addEventListener('change', updateVisualization);
updateVisualization();
map.setView(layer.getSource().getView());
现在,http://localhost:5173/应该显示一个可视化浏览器。
Visualization chooser 可视化选择器
好极了!现在,用户可以选择要呈现的可视化类型。但是如果能改变图像来源不是很好吗?下一个。
七、可视化选择器(选择可视化的图像源)
最后一个缺失部分是使用户可以选择图像源。添加图像处理器并不需要做太多的工作。我们开始吧!
首先,我们需要列出应该显示的图像列表。对于每个图像,我们希望在 <select>
元素中显示一个名称供用户选择,并且我们需要有一个 GeoTIFF URL 的base
。因此,我们将在 main.js
中添加类似以下内容的代码:
js
const images = [
{
name: 'Buenos Aires',
base: 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/21/H/UB/2021/9/S2B_21HUB_20210915_0_L2A',
},
{
name: 'Minneapolis',
base: 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/15/T/WK/2021/9/S2B_15TWK_20210918_0_L2A',
},
{
name: 'Cape Town',
base: 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/34/H/BH/2021/9/S2B_34HBH_20210922_0_L2A',
},
];
接下来,我们将添加另一个 <select>
元素,让用户选择图像。在 index.html
中,调整控件,使其看起来像这样:
js
<div id="controls">
<select id="image"></select>
<select id="visualization"></select>
</div>
回到JavaScript,我们需要为每个图像源填充一个 <option>
元素。在您的 main.js
中添加以下内容:
js
const imageSelector = document.getElementById('image');
images.forEach((image) => {
const option = document.createElement('option');
option.textContent = image.name;
imageSelector.appendChild(option);
});
现在,我们只需要对更新可视化的函数做一个小的调整,这样它就可以从选定的图像源中获取 base
URL。在 main.js
中,编辑 updateVisualization
使base动态选择,并且设置如果基图改变,调整地图视图,使其看起来像这样:
js
let previousBase;
function updateVisualization() {
// 获取当前选择的可视化选项和图像选项
const visualization = visualizations[visualizationSelector.selectedIndex];
const base = images[imageSelector.selectedIndex].base;
const newBase = base !== previousBase;
previousBase = base;
const layer = createLayer(base, visualization);
map.setLayers([layer]);
// 如果是新的基图,则调整地图视图
if (newBase) {
map.setView(layer.getSource().getView());
}
}
visualizationSelector.addEventListener('change', updateVisualization);
imageSelector.addEventListener('change', updateVisualization);
updateVisualization();
请注意,现在只有在用户选择了新的图像源时才更新视图。这比在选择新的可视化类型时缩放到完整范围更好。