返回介绍

动态颜色斜率 NDVI

发布于 2022-11-30 23:36:04 字数 7140 浏览 0 评论 0 收藏 0

动态颜色斜率 COG NDVI NDVI

本示例中的 GeoTIFF 图层取自两个Sentinel 2 资源:一个红色波段和一个近红外波段。 此图层样式包含一个 颜色(color) 表达式,可以根据这两个波段的值计算归一化差异植被指数(NDVI)。 插值(interpolate) 表达式用于将 NDVI 值映射为颜色。 颜色斜率的 "stop" 值来自应用提供的样式变量。 使用上边 input 的值,可以调整最大和最小的颜色和值。 调用 layer.updateStyleVariables() 方法来更新插值颜色表达式中使用的变量。

main.js

import 'ol/ol.css';
import GeoTIFF from 'ol/source/GeoTIFF';
import Map from 'ol/Map';
import TileLayer from 'ol/layer/WebGLTile';

const segments = 10;

const defaultMinColor = '#0300AD';
const defaultMaxColor = '#00ff00';

const defaultMinValue = -0.5;
const defaultMaxValue = 0.7;

const minColorInput = document.getElementById('min-color');
minColorInput.value = defaultMinColor;

const maxColorInput = document.getElementById('max-color');
maxColorInput.value = defaultMaxColor;

const minValueOutput = document.getElementById('min-value-output');
const minValueInput = document.getElementById('min-value-input');
minValueInput.value = defaultMinValue.toString();

const maxValueOutput = document.getElementById('max-value-output');
const maxValueInput = document.getElementById('max-value-input');
maxValueInput.value = defaultMaxValue.toString();

function getVariables() {
  const variables = {};

  const minColor = minColorInput.value;
  const maxColor = maxColorInput.value;
  const scale = chroma.scale([minColor, maxColor]).mode('lab');

  const minValue = parseFloat(minValueInput.value);
  const maxValue = parseFloat(maxValueInput.value);
  const delta = (maxValue - minValue) / segments;

  for (let i = 0; i <= segments; ++i) {
    const color = scale(i / segments).rgb();
    const value = minValue + i * delta;
    variables[`value${i}`] = value;
    variables[`red${i}`] = color[0];
    variables[`green${i}`] = color[1];
    variables[`blue${i}`] = color[2];
  }
  return variables;
}

function colors() {
  const stops = [];
  for (let i = 0; i <= segments; ++i) {
    stops[i * 2] = ['var', `value${i}`];
    const red = ['var', `red${i}`];
    const green = ['var', `green${i}`];
    const blue = ['var', `blue${i}`];
    stops[i * 2 + 1] = ['color', red, green, blue];
  }
  return stops;
}

const ndvi = [
  '/',
  ['-', ['band', 2], ['band', 1]],
  ['+', ['band', 2], ['band', 1]],
];

const source = new GeoTIFF({
  sources: [
    {
      // visible red, band 1 in the style expression above
      url: 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/2020/S2A_36QWD_20200701_0_L2A/B04.tif',
      max: 10000,
    },
    {
      // near infrared, band 2 in the style expression above
      url: 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/2020/S2A_36QWD_20200701_0_L2A/B08.tif',
      max: 10000,
    },
  ],
});

const layer = new TileLayer({
  style: {
    variables: getVariables(),
    color: ['interpolate', ['linear'], ndvi, ...colors()],
  },
  source: source,
});

function update() {
  layer.updateStyleVariables(getVariables());
  minValueOutput.innerText = parseFloat(minValueInput.value).toFixed(1);
  maxValueOutput.innerText = parseFloat(maxValueInput.value).toFixed(1);
}

minColorInput.addEventListener('input', update);
maxColorInput.addEventListener('input', update);
minValueInput.addEventListener('input', update);
maxValueInput.addEventListener('input', update);
update();

const map = new Map({
  target: 'map',
  layers: [layer],
  view: source.getView(),
});

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>NDVI with a Dynamic Color Ramp</title>
    <!-- Pointer events polyfill for old browsers, see https://caniuse.com/#feat=pointer -->
    <script src="https://unpkg.com/elm-pep"></script>
    <!-- The lines below are only needed for old environments like Internet Explorer and Android 4.x -->
    <script src="https://cdn.polyfill.io/v3/polyfill.min.js?features=fetch,requestAnimationFrame,Element.prototype.classList,TextDecoder"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/3.18.3/minified.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/chroma-js/2.1.2/chroma.min.js"></script>
    <style>
      .map {
        width: 100%;
        height:400px;
      }
      .data {
        text-align: right;
        font-family: monospace;
      }
      td {
        padding-right: 10px;
      }
      input[type="range"] {
        vertical-align: text-bottom;
      }    </style>
  </head>
  <body>
    <div id="map" class="map"></div>
    <table>
      <tbody>
        <tr>
          <td>Min NDVI</td>
          <td><input type="range" id="min-value-input" min="-1.0" max="-0.1" step="0.01"></td>
          <td class="data" id="min-value-output"></td>
          <td><input type="color" id="min-color"></td>
        </tr>
        <tr>
          <td>Max NDVI</td>
          <td><input type="range" id="max-value-input" min="0.1" max="1.0" step="0.01"></td>
          <td class="data" id="max-value-output"></td>
          <td><input type="color" id="max-color"></td>
        </tr>
      </tbody>
    </table>
    <script src="main.js"></script>
  </body>
</html>

package.json

{
  "name": "cog-colors",
  "dependencies": {
    "ol": "7.1.0"
  },
  "devDependencies": {
    "parcel": "^2.0.0"
  },
  "scripts": {
    "start": "parcel index.html",
    "build": "parcel build --public-url . index.html"
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文