本项目是使用MODIS的NDVI产品(MOD13Q1),可获取从2000年至今的所有数据,更新频率为16天
MOD13Q1 V6.1产品以每像素为基础提供植被指数(VI)值。这里有两个主要的植被层。第一种是归一化植被指数(NDVI),即现有美国国家海洋和大气管理局先进甚高分辨率辐射计(NOAA-AVHRR)衍生的NDVI的连续性指数。第二层植被层是增强型植被指数(Enhanced vegetation Index, EVI),它最大限度地减少了冠层背景变化,并在茂密植被条件下保持了敏感性。EVI还使用蓝带去除由烟雾和亚像素薄云引起的残留大气污染。MODIS NDVI和EVI产品是根据经过大气校正的双向表面反射率计算得出的,这些反射率被水、云、重气溶胶和云影遮蔽。
var panel = ui.Panel();//新建面板
// 设置面板的宽度,以及默认字体(字体等设置会在之后被覆盖)
panel.style().set({width: '20%',fontSize: '1vw',fontWeight: 'bold'});
// 在UI中插入这个面板
ui.root.insert(1, panel);
// *introduction面板
var intro_panel = ui.Panel([
// *标题(Label)
ui.Label({
// 标题想写啥:
value: 'Global NDVI Mapping',
// 设置字体
// 注:字体大小的vw(Viewport Width)、vh(Viewport Height)是基于视图窗口的单位,是css3的一部分,基于视图窗口的单位
// vw:1vw 等于视口宽度的1%
// Vh:1vh 等于视口高度的1%
style: {
fontSize: '1.5vw',//字体大小,vw会随着视窗大小而缩放
fontWeight: 'bold',//字体粗细
color: 'blue',//字体颜色
textAlign: 'center'//放置位置(居中)
},
}),
// *解释本APP的说明(Label)
ui.Label({
// 说明想说些啥:
value: //一行写不下去,就用+
'You can set the desired time range and spatial extent by drawing any shape on the map.'+
' This will allow you to obtain an average Normalized Difference Vegetation Index (NDVI) map for that region and time period. ' ,
style: {
fontSize: '1.0vw',
fontWeight: 'normal',
textAlign: 'left'//放置位置(居左)
},
}),
// *时间调节的标题(Label)
ui.Label({
value: 'Define Date Range:',
style: {
fontWeight: 'bold', //字体
fontSize: '1.0vw',//字号
padding: '0px', //边距
stretch: 'horizontal',
textAlign: 'left'//文本居左
}
}),
]);
// 将该部分放置于panel
panel.add(intro_panel);
// 预设初始日期和结束日期
var startDate = ee.Date("2023-05-01");
var endDate = ee.Date("2023-08-01");
// 初始日标题(Label),,注释同上
var Label_DateStart = ui.Label({
value: 'Start Date (yyyy-mm-dd):',
style: {
fontWeight: 'bold',
fontSize: '1.0vw',
//padding填充:顺序为 上 右 下 左 ,详见下面的padding和margin说明图
padding: '0px 0px 0px 3px',
stretch: 'horizontal',
textAlign: 'left'}
});
// 结束日标题(Label)
var Label_DateEnd = ui.Label({
value: 'End Date (yyyy-mm-dd):',
style: {
fontWeight: 'bold',
fontSize: '1.0vw',
padding: '0px 0px 0px 3px',
stretch: 'horizontal',
textAlign: 'left'}
});
// 初始日输入框(Textbox)
var Textbox__DateStart = ui.Textbox({
placeholder: "2023-05-01",//在未有任何输入前,在该文本框的数值
// onchange 事件会在域的内容改变时发生。
onChange: function(value) {
//当文本框中的内容发生变化时,startDate的值会改变
startDate = ee.Date(value);
},
// 设置输入框的宽度
style: {width: '50%', stretch: 'horizontal',padding:'0px 0px 0px 0px'}
});
// 结束日的输入框,,注释同上
var Textbox__DateEnd = ui.Textbox({
placeholder: "2023-08-01",
onChange: function(value) {
endDate = ee.Date(value);
print('endDate',endDate)
},
style: {width: '50%', stretch: 'horizontal',padding:'0px 0px 0px 0px'}
});
// 将文本和输入框水平放置,即设置放置属性为'horizontal'
panel.add(ui.Panel([Label_DateStart, Textbox__DateStart], ui.Panel.Layout.flow('horizontal')));
panel.add(ui.Panel([Label_DateEnd, Textbox__DateEnd], ui.Panel.Layout.flow('horizontal')));
// 地图中间的提示词
var map_center_panel = ui.Panel({//设置面板的属性
layout: ui.Panel.Layout.flow('vertical'),
style: {
position: 'top-center',//面板位于中间顶部
// width: '30%'
}
});
var roi_label = ui.Label({//设置label属性
value: 'Please Draw Any Shape on the Map',
style: {
fontSize: '1.3vw',
color: '#9400D3',
fontWeight: 'bold',
textAlign: 'center',
margin: '0px 0px 0px 0px'
},
})
map_center_panel.add(roi_label)//将label放置于panel
Map.add(map_center_panel);//将提示词panel放置于地图
Map.style().set('cursor', 'crosshair');//将鼠标指针形式变为十字,便于绘制
var roi_extend = ee.FeatureCollection([null]);//初始化一个FeatureCollection,用于存储绘制的空间范围
var drawingTools = Map.drawingTools(); // 初始化绘图构建
drawingTools.setLinked(false); //setLinked是控制:是否将你绘制的图形加载到(GEE JS版本的)导入区域(imports panel)
drawingTools.setDrawModes(["polygon"]); //设置绘图类型,有point, line, polygon, and rectangle可供选择
drawingTools.addLayer([], "poly", "#9400D3"); //设置所绘制的图形的名称及颜色
drawingTools.setShape("polygon"); //设置绘制模式,有point, line, polygon, and rectangle可选
drawingTools.draw(); //进入绘制状态
//debounce是允许对重复触发的每个调用序列最多调用一次,只要它们的触发间隔小于指定的间隔(以毫秒为单位)。
var getManual_poly = ui.util.debounce(function(layer) {
roi_extend = ee.FeatureCollection(layer);//将绘制的图形写入roi_extend
Map.centerObject(roi_extend);//调节地图中心
Map.addLayer(ee.Image().toByte().paint(layer, 3, 5),{},'roi_boundary')//绘制图形边缘
}, 500); //触发间隔需要小于500毫秒
drawingTools.onEdit(getManual_poly); // 当图形编辑后,触发的回调函数
drawingTools.onDraw(getManual_poly); // 当图形绘制后,触发的回调函数
drawingTools.onErase(getManual_poly); // 当图形移除后,触发的回调函数
// 放置多日均值NDVI绘制的按钮
var NDVI_btn = ui.Button({
label: "Generate NDVI mapping",//按钮上的字
style: { stretch:'horizontal'//水平放置
}});
panel.add(NDVI_btn);// 在panel中放置这个按钮
NDVI_btn.onClick(get_NDVI_mean); //设定点击按钮后触发的函数
// 放置擦除的按钮,注释同上
var clear_btn = ui.Button({
label: "Clear Layers",
style: { stretch:'horizontal'},
onClick: get_clear //这是onClick的另一种使用方式
});
panel.add(clear_btn);// 在panel中放置这个按钮
// NDVI出图配色
var ndviVis = {
min: 0,
max: 8000,
palette: [
'ffffff', 'ce7e45', 'df923d', 'f1b555', 'fcd163', '99b718', '74a901',
'66a000', '529400', '3e8601', '207401', '056201', '004c00', '023b01',
'012e01', '011d01', '011301'
],
};
// NDVI多日均值计算
function get_NDVI_mean(){
clear_drawTool();// 移除绘制的polygen,不然会挡在图层上影响美观
var NDVI_mean = ee.ImageCollection('MODIS/061/MOD13Q1')
.filterDate(startDate,endDate)//时间过滤,使用上面输入的初始日和结束日
.select('NDVI')
.mean()
.clip(roi_extend);//裁剪,使用用户绘制的图形
Map.addLayer(NDVI_mean,ndviVis,'NDVI_mean')//绘制
}
// 函数:清除地图所有图层
function get_clear(){
Map.clear()//清除地图所有图层
// 将基础配置重新加载
// Map.addLayer(continent_bound_image, {palette: "red"}, 'continent bound')
Map.add(map_center_panel);//将提示词panel放置于地图
clear_drawTool()
}
// 清除绘图组件,注释同上
function clear_drawTool(){
drawingTools.clear();
drawingTools.setLinked(false);
drawingTools.setDrawModes(["polygon"]);
drawingTools.addLayer([], "poly", "#9400D3");
drawingTools.setShape("polygon");
drawingTools.draw();
drawingTools.onEdit(getManual_poly);
drawingTools.onDraw(getManual_poly);
drawingTools.onErase(getManual_poly);
}
首先要绘制一个区域范围
在地图上任意连线,首尾点重合则绘制完成。
输入日期范围,然后生成NDVI,得到的NDVI是长时间的一个平均值