它是衡量植物生長狀況的指標,根據植被對近紅外光與紅光的反射特性計算而得。指數值範圍從 -1 到 1,數值越高代表綠意越旺盛,常用來分析森林覆蓋變化、農作物生長週期,甚至是氣候變遷影響。
這段程式使用的衛星資料來自MODIS。MODIS 是美國 NASA Terra 與 Aqua 衛星搭載的儀器,從 2000 年起每天環繞地球,觀察大氣、海洋與陸地變化。MOD13Q1 是 MODIS 的 NDVI 資料產品,每 16 天提供一次雲遮減少、經過處理的高品質 NDVI 值,解析度約為 250 公尺。
// ===[ 1. 使用者設定區塊 ]===
var config = {
startYear: 2000,
endYear: 2024,
scale: 250, // MODIS 的空間解析度
timeScale: 'yearly' // 可選:'yearly', 'quarterly', 'monthly', 'original'
};
// ===[ 2. 幾何區域:使用你畫的範圍 ]===
Map.centerObject(geometry, 12); // geometry 為互動選取區域
Map.addLayer(geometry, {color: 'red'}, '分析範圍');
// ===[ 3. 載入 MODIS NDVI 並正規化 ]===
var modis = ee.ImageCollection("MODIS/006/MOD13Q1")
.filterBounds(geometry)
.filterDate(config.startYear + '-01-01', config.endYear + '-12-31')
.select('NDVI');
var scaled = modis.map(function(img) {
return img.multiply(0.0001)
.copyProperties(img, ['system:time_start']);
});
// ===[ 4. 時間尺度函式 ]===
var timeReduced;
if (config.timeScale === 'yearly') {
var years = ee.List.sequence(config.startYear, config.endYear);
timeReduced = ee.ImageCollection.fromImages(
years.map(function(y) {
var start = ee.Date.fromYMD(y, 1, 1);
var end = ee.Date.fromYMD(y, 12, 31);
return scaled.filterDate(start, end).mean()
.set('system:time_start', start.millis())
.set('label', y.toString());
})
);
} else if (config.timeScale === 'quarterly') {
var quarters = ee.List.sequence(0, ee.Number(config.endYear).subtract(config.startYear).multiply(4).subtract(1));
timeReduced = ee.ImageCollection.fromImages(
quarters.map(function(q) {
var start = ee.Date(config.startYear + '-01-01').advance(q, 'quarter');
var end = start.advance(1, 'quarter');
return scaled.filterDate(start, end).mean()
.set('system:time_start', start.millis())
.set('label', start.format('YYYY Q'));
})
);
} else if (config.timeScale === 'monthly') {
var months = ee.List.sequence(0, ee.Date(config.endYear + '-12-01').difference(ee.Date(config.startYear + '-01-01'), 'month').subtract(1));
timeReduced = ee.ImageCollection.fromImages(
months.map(function(m) {
var start = ee.Date(config.startYear + '-01-01').advance(m, 'month');
var end = start.advance(1, 'month');
return scaled.filterDate(start, end).mean()
.set('system:time_start', start.millis())
.set('label', start.format('YYYY-MM'));
})
);
} else if (config.timeScale === 'original') {
timeReduced = scaled;
} else {
throw new Error('Unsupported timeScale: ' + config.timeScale);
}
// ===[ 5. 繪製圖表 ]===
var chart = ui.Chart.image.series({
imageCollection: timeReduced.select('NDVI'),
region: geometry,
reducer: ee.Reducer.mean(),
scale: config.scale,
xProperty: 'system:time_start'
}).setOptions({
title: 'NDVI 時間序列變化(' + config.timeScale + ')',
hAxis: {title: '時間'},
vAxis: {title: 'NDVI(正規化)'},
lineWidth: 2,
pointSize: 3
});
print(chart);
// ===[ 6. 顯示最新 NDVI 圖層 ]===
var latest = timeReduced.sort('system:time_start', false).first();
Map.addLayer(latest, {min: 0, max: 1, palette: ['white', 'green']}, '最新 NDVI (' + config.timeScale + ')');
// ===[ 7. 滑桿與時間標籤 UI ]===
var timeLabels = timeReduced.aggregate_array('label').getInfo();
// 建立時間標籤
var dateLabel = ui.Label('日期:' + timeLabels[timeLabels.length - 1]);
// 建立滑桿控制時間點
var slider = ui.Slider({
min: 0,
max: timeLabels.length - 1,
step: 1,
value: timeLabels.length - 1,
style: {width: '400px'}
});
// 初始圖層
var currentImage = ee.Image(timeReduced.toList(timeReduced.size()).get(timeLabels.length - 1));
var currentLayer = ui.Map.Layer(currentImage, {min:0, max:1, palette:['white','green']}, 'NDVI ' + timeLabels[timeLabels.length - 1]);
Map.layers().set(0, currentLayer);
// 當滑桿變動時更新圖層與時間標籤
slider.onChange(function(index) {
var label = timeLabels[index];
dateLabel.setValue('日期:' + label);
var img = ee.Image(timeReduced.toList(timeReduced.size()).get(index));
Map.layers().set(0, ui.Map.Layer(img, {min:0, max:1, palette:['white','green']}, 'NDVI ' + label));
});
// 加入 UI 元件(先建立一個 panel)
var panel = ui.Panel({
widgets: [dateLabel, slider],
layout: ui.Panel.Layout.flow('vertical'),
style: {position: 'bottom-left'}
});
Map.add(panel);