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. ก่อนเริ่มต้น ให้ทำตามวิธีการในหัวข้อ ตั้งค่าโปรเจ็กต์ Cloud ที่เปิดใช้ Earth Engine จดรหัสไคลเอ็นต์ที่ได้รับในส่วน "ตั้งค่า OAuth 2.0" เนื่องจากแอปพลิเคชันของคุณจะอนุญาตให้ผู้ใช้ลงชื่อเข้าใช้ด้วยบัญชี Google ของตนเอง คุณจึงข้ามส่วน "สร้างและลงทะเบียนบัญชีบริการ" ได้
  2. เปิดใช้ Maps JavaScript API สำหรับโปรเจ็กต์

รับคีย์ Maps API

ดูวิธีรับคีย์ API ในเอกสารประกอบของ Maps JavaScript API เพื่อเรียนรู้วิธีรับคีย์ API ที่อนุญาตให้คุณ ใช้ Maps JavaScript 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 เพื่อกำหนดขนาดและสีพื้นหลังของแผนที่ที่แสดงขณะเริ่มต้น
  • กำหนดปุ่ม "ลงชื่อเข้าใช้ด้วย Google" ที่เรียกใช้ฟังก์ชัน onSignInButtonClick() เมื่อคลิก ซึ่งเราจะกำหนดฟังก์ชันนี้ใน JavaScript ในส่วนถัดไป
  • กำหนดองค์ประกอบว่างที่จะมีแผนที่เมื่อเริ่มต้นแล้ว
  • เพิ่มบล็อก <script> ว่างเพื่อเก็บโค้ด JavaScript ที่กำหนดไว้ด้านล่าง

ขั้นตอนที่ 2 กำหนดลักษณะการทำงานใน JavaScript

ในขั้นตอนต่อไปนี้ คุณสามารถวางโค้ด JavaScript ไว้ในแท็ก <script> ได้โดยตรง

กำหนดฟังก์ชันเรียกกลับเพื่อตั้งค่า API และแผนที่

กำหนดฟังก์ชันเพื่อดำเนินการเมื่อผู้ใช้ลงชื่อเข้าใช้แล้ว ระบบจะเริ่มต้นและเรียกใช้ Earth Engine API ได้ก็ต่อเมื่อผู้ใช้ได้รับการตรวจสอบสิทธิ์แล้วเท่านั้น ซึ่งเราจะอธิบายรายละเอียดในเร็วๆ นี้

ตัวอย่างนี้จะเริ่มต้น Earth Engine และ 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 และ 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_KEY และ YOUR_CLIENT_ID ด้วยคีย์ Maps API และรหัสไคลเอ็นต์ OAuth ที่ได้รับใน ข้อกำหนดเบื้องต้น (คุณสามารถคลิกตัวยึดตำแหน่งเหล่านี้ ในโค้ดด้านล่างเพื่อแทรกโดยอัตโนมัติ) และแทนที่ 'my-project' ด้วยรหัสโปรเจ็กต์ Google Cloud ของคุณ

<!-- 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>