クライアントサイドのウェブアプリでの Earth Engine API

このガイドでは、Earth Engine でオンザフライで計算された結果を表示するインタラクティブな地図を含むウェブページを作成する方法について説明します。HTML、CSS、JavaScript について初級から中級の知識がある方に適しています。

以下は、このガイドで作成するインタラクティブ マップのデモです。Earth Engine で計算されたグランド キャニオンの地形の傾斜が、さまざまな濃さのグレーで表示されています。地図をパンやズームして、他のエリアの結果を計算して表示できます。なお、デモにログインする必要があります。

ここで説明するアプローチは、通常、シングルページ アプリケーション(SPA)を作成するときに使用されます。SPA では、サーバーからページを再読み込みすることなく、ウェブブラウザでアプリ全体を使用できます。そのため、これらのアプリではカスタム サーバーサイド コンポーネントの開発とホスティングは必要ありません。

アプリのコードはユーザーのウェブブラウザ(クライアントサイド実行とも呼ばれます)で実行されるため、開発者はサービス アカウントの秘密鍵などの機密性の高い認証情報をアプリケーションに直接埋め込むべきではありません。代わりに、アプリケーションのユーザーは、Earth Engine へのアクセス用に登録された独自のアカウントを使用して認証する必要があります。

このガイドで説明する内容:

  1. ユーザーが Earth Engine アカウントを使用してログインできるボタンを表示します。
  2. Earth Engine で基本的な分析を定義する。
  3. Maps JavaScript API を使用して結果を表示するインタラクティブな地図を埋め込みます。

前提条件

Cloud プロジェクトを設定する

  1. 始める前に、Earth Engine 対応の Cloud プロジェクトを設定するの手順に沿って操作します。「OAuth 2.0 を設定する」セクションで取得したクライアント ID をメモします。アプリケーションではユーザーが自分の Google アカウントでログインできるようにするため、「サービス アカウントを作成して登録する」のセクションはスキップできます。
  2. プロジェクトで Maps JavaScript API を有効にします

Maps API キーを取得する

ウェブ アプリケーションで Maps JavaScript API を使用できる API キーを取得する方法については、Maps JavaScript API の API ドキュメントの API キーを取得するをご覧ください。

API キーを制限するセクションの手順に沿って、API キーを使用したリクエストのみが承認されるようにすることを強くおすすめします。

アプリを作成する

ステップ 1. HTML ページを作成する

まず、次のように基本的な HTML ウェブページを定義します。

<!DOCTYPE html>
<html>
  <head>
    <style>
      /* Set the size of the div element that contains the map. */
      #map-container {
        height: 400px;
        width: 100%;
        background-color: #eee;
      }
    </style>
  </head>
  <body>
    <!-- The "Sign in with Google" button, initially hidden. -->
    <input
      id="g-sign-in"
      type="image"
      src="https://developers.google.com/identity/images/btn_google_signin_light_normal_web.png"
      onclick="onSignInButtonClick()"
      alt="Sign in with Google"
      hidden
    />

    <!-- Element where map will be added. -->
    <div id="map-container"></div>
    <script>
      // JavaScript code goes here.
    </script>
  </body>
</html>

この簡易 HTML は、次の処理を行います。

  • CSS スタイルを使用して、初期化中に表示される地図のサイズと背景色を定義します。
  • クリック時に関数 onSignInButtonClick() を呼び出す「Google でログイン」ボタンを定義します。この関数は、次のセクションで JavaScript で定義します。
  • 初期化後に地図を含む空の要素を定義します。
  • 以下で定義する JavaScript コードを保持する空の <script> ブロックを追加します。

ステップ 2. JavaScript で動作を定義する

以降の手順では、JavaScript コードを <script> タグ内に直接配置できます。

API と地図を設定するコールバックを定義する

ユーザーがログインした後に処理を行う関数を定義します。Earth Engine API は、ユーザーが認証された後にのみ初期化して呼び出すことができます。詳細については、後日お知らせいたします。

この例では、Earth Engine API と Maps API を初期化し、地形の傾斜をオンデマンドで計算するタイルソースを作成して、Maps JavaScript API によって表示されるオーバーレイとして地図にタイルソースを追加します。

// Initializes Maps JavaScript API and Earth Engine API, instructing the map
// to pull tiles from Earth Engine and to overlay them on the map.
function setUpMap() {
  // Hide the sign-in button.
  document.getElementById("g-sign-in").setAttribute("hidden", "true");

  // Initialize the Earth Engine API. Must be called once before using the API.
  ee.initialize(null, null, null, null, null, 'my-project');

  // Get a reference to the placeholder DOM element to contain the map.
  const mapContainerEl = document.getElementById("map-container");

  // Create an interactive map inside the placeholder DOM element.
  const embeddedMap = new google.maps.Map(mapContainerEl, {
    // Pan and zoom initial map viewport to Grand Canyon.
    center: {lng: -112.8598, lat: 36.2841},
    zoom: 9,
  });

  // Obtain reference to digital elevation model and apply algorithm to
  // calculate slope.
  const srtm = ee.Image("CGIAR/SRTM90_V4");
  const slope = ee.Terrain.slope(srtm);

  // Create a new tile source to fetch visible tiles on demand and display them
  // on the map.
  const mapId = slope.getMap({min: 0, max: 60});
  const tileSource = new ee.layers.EarthEngineTileSource(mapId);
  const overlay = new ee.layers.ImageOverlay(tileSource);
  embeddedMap.overlayMapTypes.push(overlay);
}

ログインボタンのクリックのハンドラを定義する

次に、ログイン ボタンがクリックされたときにログイン ポップアップを表示する関数を追加します。成功すると、setUp() メソッドが呼び出されます。

// Handles clicks on the sign-in button.
function onSignInButtonClick() {
  // Display popup allowing the user to sign in with their Google account and to
  // grant appropriate permissions to the app.
  ee.data.authenticateViaPopup(setUpMap);
}

このコールバックは、上記の HTML のボタンの onclick 属性を介して関連付けられています。この例では、ページの読み込み時にログインボタンが最初は非表示になっていることに注意してください。次のセクションでは、ボタンを表示する前にユーザーがログインしているかどうかを確認します。

メイン エントリ ポイントを定義する

次に、ページが読み込まれたときに最初に実行されるトップレベルのコードを定義します。このコードでは、Earth Engine の組み込み認証ヘルパー関数 ee.data.authenticateViaPopup() を使用して、ユーザーがすでにログインしているかどうかを確認します。ユーザーがログインしている場合、この関数は適切な権限をリクエストし、成功した場合は setUp() を呼び出して Earth Engine API と Maps API を初期化します。

ユーザーがログインしていない場合は、ログインボタンが表示されます。ユーザーがボタンをクリックすると、onSignInButtonClick() がトリガーされ、ポップアップが表示されて setUp() が呼び出されます。

// If the user is signed in, display a popup requesting permissions needed to
// run the app, otherwise show the sign-in button.
ee.data.authenticateViaOauth(
  // The OAuth Client ID defined above.
  CLIENT_ID,
  // Callback invoked immediately when user is already signed in.
  setUpMap,
  // Show authentication errors in a popup.
  alert,
  // Request permission to only read and compute Earth Engine data on behalf of
  // user.
  /* extraScopes = */ ['https://www.googleapis.com/auth/earthengine.readonly'],
  // Show sign-in button if reusing existing credentials fails.
  () => document.getElementById("g-sign-in").removeAttribute("hidden"),
  // Don't require ability to write and access Cloud Platform on behalf of the
  // user.
  /* opt_suppressDefaultScopes = */ true
);

実際に試す

このガイドで説明する完全なソリューションは次のとおりです。サンプルコードの右上隅に 3 つのボタンがあります。左端のボタンをクリックすると、JSFiddle でサンプルが開きます。

YOUR_API_KEYYOUR_CLIENT_ID を、前提条件で取得した Maps API キーと OAuth クライアント ID に置き換えます(下のコードのプレースホルダをクリックすると、自動的に挿入されます)。また、'my-project' を Google Cloud プロジェクト ID に置き換えます。

<!-- Load Maps JavaScript API. For production apps, append you own ?key=YOUR_API_KEY. -->

<script src="https://maps.googleapis.com/maps/api/js?key="></script>
<script src="https://ajax.googleapis.com/ajax/libs/earthengine/0.1.365/earthengine-api.min.js"></script>
<!-- The "Sign in with Google" button, initially hidden. -->
<input
  id="g-sign-in"
  type="image"
  src="https://developers.google.com/identity/images/btn_google_signin_light_normal_web.png"
  onclick="onSignInButtonClick()"
  alt="Sign in with Google"
  hidden
/>

<!-- Element where map will be added. -->
<div id="map-container"></div>
/* Set the size of the div element that contains the map. */
  #map-container {
    height: 400px;
    width: 100%;
    background-color: #eee;
  }
// The OAuth Client ID from the Google Developers Console.
// REMINDER: Be sure to add a valid ID here!
const CLIENT_ID = "";

// Initializes Maps JavaScript API and Earth Engine API, instructing the map
// to pull tiles from Earth Engine and to overlay them on the map.
function setUpMap() {
  // Hide the sign-in button.
  document.getElementById("g-sign-in").setAttribute("hidden", "true");

  // Initialize the Earth Engine API. Must be called once before using the API.
  ee.initialize(null, null, null, null, null, 'my-project');

  // Get a reference to the placeholder DOM element to contain the map.
  const mapContainerEl = document.getElementById("map-container");

  // Create an interactive map inside the placeholder DOM element.
  const embeddedMap = new google.maps.Map(mapContainerEl, {
    // Pan and zoom initial map viewport to Grand Canyon.
    center: {lng: -112.8598, lat: 36.2841},
    zoom: 9,
  });

  // Obtain reference to digital elevation model and apply algorithm to
  // calculate slope.
  const srtm = ee.Image("CGIAR/SRTM90_V4");
  const slope = ee.Terrain.slope(srtm);

  // Create a new tile source to fetch visible tiles on demand and display them
  // on the map.
  const mapId = slope.getMap({min: 0, max: 60});
  const tileSource = new ee.layers.EarthEngineTileSource(mapId);
  const overlay = new ee.layers.ImageOverlay(tileSource);
  embeddedMap.overlayMapTypes.push(overlay);
}

// Handles clicks on the sign-in button.
function onSignInButtonClick() {
  // Display popup allowing the user to sign in with their Google account and to
  // grant appropriate permissions to the app.
  ee.data.authenticateViaPopup(setUpMap);
}

// If the user is signed in, display a popup requesting permissions needed to
// run the app, otherwise show the sign-in button.
ee.data.authenticateViaOauth(
  // The OAuth Client ID defined above.
  CLIENT_ID,
  // Callback invoked immediately when user is already signed in.
  setUpMap,
  // Show authentication errors in a popup.
  alert,
  // Request permission to only read and compute Earth Engine data on behalf of
  // user.
  /* extraScopes = */ ['https://www.googleapis.com/auth/earthengine.readonly'],
  // Show sign-in button if reusing existing credentials fails.
  () => document.getElementById("g-sign-in").removeAttribute("hidden"),
  // Don't require ability to write and access Cloud Platform on behalf of the
  // user.
  /* opt_suppressDefaultScopes = */ true
);
<!DOCTYPE html>
<html>
  <head>
    <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/earthengine/0.1.365/earthengine-api.min.js"></script>
    <style>
      /* Set the size of the div element that contains the map. */
      #map-container {
        height: 400px;
        width: 100%;
        background-color: #eee;
      }
    </style>
  </head>
  <body>
    <!-- The "Sign in with Google" button, initially hidden. -->
    <input
      id="g-sign-in"
      type="image"
      src="https://developers.google.com/identity/images/btn_google_signin_light_normal_web.png"
      onclick="onSignInButtonClick()"
      alt="Sign in with Google"
      hidden
    />

    <!-- Element where map will be added. -->
    <div id="map-container"></div>
    <script>
      // The OAuth Client ID from the Google Developers Console.
      const CLIENT_ID = "YOUR_CLIENT_ID";
      
      // Initializes Maps JavaScript API and Earth Engine API, instructing the map
      // to pull tiles from Earth Engine and to overlay them on the map.
      function setUpMap() {
        // Hide the sign-in button.
        document.getElementById("g-sign-in").setAttribute("hidden", "true");
      
        // Initialize the Earth Engine API. Must be called once before using the API.
        ee.initialize(null, null, null, null, null, 'my-project');
      
        // Get a reference to the placeholder DOM element to contain the map.
        const mapContainerEl = document.getElementById("map-container");
      
        // Create an interactive map inside the placeholder DOM element.
        const embeddedMap = new google.maps.Map(mapContainerEl, {
          // Pan and zoom initial map viewport to Grand Canyon.
          center: {lng: -112.8598, lat: 36.2841},
          zoom: 9,
        });
      
        // Obtain reference to digital elevation model and apply algorithm to
        // calculate slope.
        const srtm = ee.Image("CGIAR/SRTM90_V4");
        const slope = ee.Terrain.slope(srtm);
      
        // Create a new tile source to fetch visible tiles on demand and display them
        // on the map.
        const mapId = slope.getMap({min: 0, max: 60});
        const tileSource = new ee.layers.EarthEngineTileSource(mapId);
        const overlay = new ee.layers.ImageOverlay(tileSource);
        embeddedMap.overlayMapTypes.push(overlay);
      }
      
      // Handles clicks on the sign-in button.
      function onSignInButtonClick() {
        // Display popup allowing the user to sign in with their Google account and to
        // grant appropriate permissions to the app.
        ee.data.authenticateViaPopup(setUpMap);
      }
      
      // If the user is signed in, display a popup requesting permissions needed to
      // run the app, otherwise show the sign-in button.
      ee.data.authenticateViaOauth(
        // The OAuth Client ID defined above.
        CLIENT_ID,
        // Callback invoked immediately when user is already signed in.
        setUpMap,
        // Show authentication errors in a popup.
        alert,
        // Request permission to only read and compute Earth Engine data on behalf of
        // user.
        /* extraScopes = */ ['https://www.googleapis.com/auth/earthengine.readonly'],
        // Show sign-in button if reusing existing credentials fails.
        () => document.getElementById("g-sign-in").removeAttribute("hidden"),
        // Don't require ability to write and access Cloud Platform on behalf of the
        // user.
        /* opt_suppressDefaultScopes = */ true
      );
    </script>
  </body>
</html>