氣象模組使用教學


[info] 小提示:

程式碼連結:https://doc-3dgdp.colife.org.tw/samplecode/#src/testweb/weather-sample/

取得即時氣象圖

使用此功能可以從氣象局公開資料中取得即時氣象圖,參數中的觀測API代碼及API Key請開發人員至氣象局資料開放平台中取得。

[info] 小提示:

  1. 氣象局資料開放平台使用說明:點此前往
  2. 氣象局Opendata API線上說明文件:點此前往
  3. 氣象局資料開放平台觀測資料代碼:點此前往


[warning] 注意事項:

記得要去氣象局申請 API Key 才能使用 Sample 來做測試。

首先要先撰寫一個最基本的圖台,並在介面上新增一個選單用來控制要取得哪種類型的氣象圖。
其中每個項目的value為每個種類氣象圖的觀測API代碼。

[warning] 注意事項:

並不是所有氣象局資料開放平台中的觀測資料都適用於圖台,請依需求審慎選擇圖資,並於正式上線使用前做好測試。

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <meta charset="utf-8" />
    <script src="https://sample.pilotgaea.com.tw/demo/index/src/PGWebJS/13.0/PGWeb3D.min.js"></script>
    <link
      rel="stylesheet"
      type="text/css"
      href="https://sample.pilotgaea.com.tw/demo/index/src/PGWebJS/13.0/css/PGWeb3D.css"
    />
    <link
      rel="stylesheet"
      type="text/css"
      href="https://sample.pilotgaea.com.tw/demo/index/css/main.css"
    />
    <link rel="stylesheet" type="text/css" href="./load.css" />
  </head>

  <body>
    <div
      id="MyControl"
      style="
        position: absolute;
        z-index: 1;
        color: white;
        background-color: black;
      "
    >
      <div>
        即時氣象圖:
        <select id="source">
          <option value="O-A0038-001">溫度分布</option>
          <option value="O-A0058-005">雷達回波整合(較大範圍)</option>
          <option value="O-A0058-006">雷達回波整合(鄰近區域)</option>
          <option value="O-B0028-003">紅外線彩色衛星雲圖-東亞</option>
        </select>
        <button id="Start">取得最新資料</button>
        <button id="Clear">清除</button>
      </div>
      <div>
        API Key:<input type="text" placeholder="請至官網 https://opendata.cwa.gov.tw/申請" id="apiKeyInput" style="width: 60%;">
      </div>
      <div
        id="MyMap"
        style="width: 100%; height: 100%; position: absolute; top: 0; left: 0;"
      ></div>
      <script src="main.js"></script>
    </body>
</html>

main.js

let terrainview = new window.ov.TerrainView("MyMap");
let weather = null;
let widgetTimeline = null;
let widgetTimelinePlayer = null;
let historylayer = null;
let weatherlayer = null;

terrainview.openTerrain({
  url: "http://127.0.0.1:8080",
  identifier: "範例地形圖",
  callback: openCallback,
  urlTemplate: "https://sample.pilotgaea.com.tw/Oview.aspx?{URL}"
});

// 在使用其他圖層前必須要先讀入地形 其他圖層的新增都會在callback中
// 天氣API:https://sample.pilotgaea.com.tw/demo/Reference/v13/js3d/ov.WeatherModule.html#addRadarReflectivityHistoryLayer
// 時間軸API:https://sample.pilotgaea.com.tw/demo/Reference/v13/js3d/ov.Widget.Timeline.html
// 時間軸撥放器API:https://sample.pilotgaea.com.tw/demo/Reference/v13/js3d/ov.Widget.TimelinePlayer.html

function openCallback(result) {
  // 設定底圖
  terrainview.setBaseLayer({
    url: "BING_MAP",
    identifier: "IMAGE",
    urlTemplate: "https://sample.pilotgaea.com.tw/Oview.aspx?{URL}"
  });
  // 設定初始位置
  let initialPos = new window.GeoPoint(
    121.2347878442796,
    23.427553934089445,
    465850.0013822634
  );
  let initialV = new window.Geo3DPoint(0, 0, -1);
  let initialUp = new window.Geo3DPoint(0, 1, 0);
  let initialCamera = new window.ov.Camera(initialPos, initialV, initialUp);
  terrainview.gotoCamera(initialCamera, false);

  // 新增天氣物件
  weather = terrainview.getModule("weather");
  weather.proxy = "https://sample.pilotgaea.com.tw/weather.ashx?"; // 設定代理伺服器位置
  // weather.authorization = ""; // 填入氣象局API Key


  // 新增時間軸物件
  widgetTimeline = new window.ov.Widget.Timeline({
    view: terrainview,
    style: { left: "10%", width: "88%" },
    isRepeat: true
  });

  // 新增時間軸撥放器物件
  widgetTimelinePlayer = new window.ov.Widget.TimelinePlayer({
    view: terrainview,
    timeline: widgetTimeline,
    playSpeed: 1500.0
  });
}

// 設定開始按鈕的Click事件。
document.getElementById("Start").addEventListener("click", function () {

});
// 設定清除按鈕的Click事件。
document.getElementById("Clear").addEventListener("click", function () {

});

再來我們要把開始與清除按鈕的點擊事件加進我們撰寫好的main.js中。

main.js

let terrainview = new window.ov.TerrainView("MyMap");
let weather = null;
let widgetTimeline = null;
let widgetTimelinePlayer = null;
let historylayer = null;
let weatherlayer = null;

terrainview.openTerrain({
  url: "http://127.0.0.1:8080",
  identifier: "範例地形圖",
  callback: openCallback,
  urlTemplate: "https://sample.pilotgaea.com.tw/Oview.aspx?{URL}"
});

// 在使用其他圖層前必須要先讀入地形 其他圖層的新增都會在callback中
// 天氣API:https://sample.pilotgaea.com.tw/demo/Reference/v13/js3d/ov.WeatherModule.html#addRadarReflectivityHistoryLayer
// 時間軸API:https://sample.pilotgaea.com.tw/demo/Reference/v13/js3d/ov.Widget.Timeline.html
// 時間軸撥放器API:https://sample.pilotgaea.com.tw/demo/Reference/v13/js3d/ov.Widget.TimelinePlayer.html

function openCallback(result) {
  // 設定底圖
  terrainview.setBaseLayer({
    url: "BING_MAP",
    identifier: "IMAGE",
    urlTemplate: "https://sample.pilotgaea.com.tw/Oview.aspx?{URL}"
  });
  // 設定初始位置
  let initialPos = new window.GeoPoint(
    121.2347878442796,
    23.427553934089445,
    465850.0013822634
  );
  let initialV = new window.Geo3DPoint(0, 0, -1);
  let initialUp = new window.Geo3DPoint(0, 1, 0);
  let initialCamera = new window.ov.Camera(initialPos, initialV, initialUp);
  terrainview.gotoCamera(initialCamera, false);

  // 新增天氣物件
  weather = terrainview.getModule("weather");
  weather.proxy = "https://sample.pilotgaea.com.tw/weather.ashx?"; // 設定代理伺服器位置
  // weather.authorization = ""; // 填入氣象局API Key


  // 新增時間軸物件
  widgetTimeline = new window.ov.Widget.Timeline({
    view: terrainview,
    style: { left: "10%", width: "88%" },
    isRepeat: true
  });

  // 新增時間軸撥放器物件
  widgetTimelinePlayer = new window.ov.Widget.TimelinePlayer({
    view: terrainview,
    timeline: widgetTimeline,
    playSpeed: 1500.0
  });
}

document.getElementById("Start").addEventListener("click", function () {
  weather.authorization = document.getElementById('apiKeyInput').value; //帶入使用者輸入的氣象局API Key
  let v = document.getElementById("source").value;
  document.getElementById("Start").disabled = true;
  document.getElementById("loader").style.display = "block";
  if (v) {
    if (weatherlayer) {
      weather.removeLayer(weatherlayer);
      weatherlayer = null;
      terrainview.updateScreen();
    }
    weather.addWeatherImageLayer(
      {
        api: v
      },
      function (rtn) {
        if (window.IsString(rtn)) {
          window.ov.UI.Alertify.Error(rtn);
        } else {
          window.ov.UI.Alertify.Notify("完成");
          weatherlayer = rtn;
        }

        document.getElementById("loader").style.display = "none";
        document.getElementById("Start").disabled = false;
      }
    );
  }
});

document.getElementById("Clear").addEventListener("click", function () {
  if (weatherlayer) {
    weather.removeLayer(weatherlayer);
    terrainview.updateScreen();
    weatherlayer = null;
  }
});

取得雷達回波歷史圖

透過此功能可以取得歷史雷達回波圖,並結合時間軸及特殊內插方法做出雷達回波圖的動畫呈現。

首先要先撰寫一個最基本的圖台,並在介面上新增一系列控制項用來控制參數。

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <meta charset="utf-8" />
    <script src="https://sample.pilotgaea.com.tw/demo/index/src/PGWebJS/13.0/PGWeb3D.min.js"></script>
    <link
      rel="stylesheet"
      type="text/css"
      href="https://sample.pilotgaea.com.tw/demo/index/src/PGWebJS/13.0/css/PGWeb3D.css"
    />
    <link
      rel="stylesheet"
      type="text/css"
      href="https://sample.pilotgaea.com.tw/demo/index/css/main.css"
    />
    <link rel="stylesheet" type="text/css" href="./load.css" />
  </head>

  <body>
    <div
      id="MyControl"
      style="
        position: absolute;
        z-index: 1;
        color: white;
        background-color: black;
      "
    >
      <div>
        雷達回波歷史圖:
        <select id="limit" onchange="change()">
          <option value="1">一小時</option>
          <option value="2">兩小時</option>
          <option value="3">三小時</option>
          <option value="4">四小時</option>
          <option value="5">五小時</option>
          <option value="6">六小時</option>
          <option value="7">七小時</option>
          <option value="8">八小時</option>
          <option value="9">九小時</option>
          <option value="10">十小時</option>
          <option value="11">十一小時</option>
          <option value="12">十二小時</option>
        </select>
        <button id="HistoryStart">開始</button>
        <button id="HistoryClear">清除</button>
      </div>
      <div>
        API Key:<input type="text" placeholder="請至官網 https://opendata.cwa.gov.tw/申請" id="apiKeyInput" style="width: 60%;">
      </div>
    </div>
    <div
      id="MyMap"
      style="width: 100%; height: 100%; position: absolute; top: 0; left: 0;"
    ></div>
    <script src="main.js"></script>
  </body>
</html>

main.js

let terrainview = new window.ov.TerrainView("MyMap");
let weather = null;
let widgetTimeline = null;
let widgetTimelinePlayer = null;
let historylayer = null;
let weatherlayer = null;

terrainview.openTerrain({
  url: "http://127.0.0.1:8080",
  identifier: "範例地形圖",
  callback: openCallback,
  urlTemplate: "https://sample.pilotgaea.com.tw/Oview.aspx?{URL}"
});

// 在使用其他圖層前必須要先讀入地形 其他圖層的新增都會在callback中
// 天氣API:https://sample.pilotgaea.com.tw/demo/Reference/v13/js3d/ov.WeatherModule.html#addRadarReflectivityHistoryLayer
// 時間軸API:https://sample.pilotgaea.com.tw/demo/Reference/v13/js3d/ov.Widget.Timeline.html
// 時間軸撥放器API:https://sample.pilotgaea.com.tw/demo/Reference/v13/js3d/ov.Widget.TimelinePlayer.html

function openCallback(result) {
  // 設定底圖
  terrainview.setBaseLayer({
    url: "BING_MAP",
    identifier: "IMAGE",
    urlTemplate: "https://sample.pilotgaea.com.tw/Oview.aspx?{URL}"
  });
  // 設定初始位置
  let initialPos = new window.GeoPoint(
    121.2347878442796,
    23.427553934089445,
    465850.0013822634
  );
  let initialV = new window.Geo3DPoint(0, 0, -1);
  let initialUp = new window.Geo3DPoint(0, 1, 0);
  let initialCamera = new window.ov.Camera(initialPos, initialV, initialUp);
  terrainview.gotoCamera(initialCamera, false);

  // 新增天氣物件
  weather = terrainview.getModule("weather");
  weather.proxy = "https://sample.pilotgaea.com.tw/weather.ashx?"; // 設定代理伺服器位置
  // weather.authorization = ""; // 填入氣象局API Key


  // 新增時間軸物件
  widgetTimeline = new window.ov.Widget.Timeline({
    view: terrainview,
    style: { left: "10%", width: "88%" },
    isRepeat: true
  });

  // 新增時間軸撥放器物件
  widgetTimelinePlayer = new window.ov.Widget.TimelinePlayer({
    view: terrainview,
    timeline: widgetTimeline,
    playSpeed: 1500.0
  });
}

// 設定開始按鈕的Click事件。
document.getElementById("HistoryStart").addEventListener("click", function () {

});

// 設定清除按鈕的Click事件。
document.getElementById("HistoryClear").addEventListener("click", function () {

});

再來我們要把開始與清除按鈕的點擊事件加進我們撰寫好的main.js中。

[warning] 取圖規則注意事項:

為節省網路流量資源,此功能設有"資料筆數上限"之限制。
若時間區間中取得的圖片數量大於"資料筆數上限",則以時間區間終點往前取"資料筆數上限"筆數之資料。
反之,則以時間區間中取得的圖片數量為主。

main.js

let terrainview = new window.ov.TerrainView("MyMap");
let weather = null;
let widgetTimeline = null;
let widgetTimelinePlayer = null;
let historylayer = null;
let weatherlayer = null;

terrainview.openTerrain({
  url: "http://127.0.0.1:8080",
  identifier: "範例地形圖",
  callback: openCallback,
  urlTemplate: "https://sample.pilotgaea.com.tw/Oview.aspx?{URL}"
});

// 在使用其他圖層前必須要先讀入地形 其他圖層的新增都會在callback中
// 天氣API:https://sample.pilotgaea.com.tw/demo/Reference/v13/js3d/ov.WeatherModule.html#addRadarReflectivityHistoryLayer
// 時間軸API:https://sample.pilotgaea.com.tw/demo/Reference/v13/js3d/ov.Widget.Timeline.html
// 時間軸撥放器API:https://sample.pilotgaea.com.tw/demo/Reference/v13/js3d/ov.Widget.TimelinePlayer.html

function openCallback(result) {
  // 設定底圖
  terrainview.setBaseLayer({
    url: "BING_MAP",
    identifier: "IMAGE",
    urlTemplate: "https://sample.pilotgaea.com.tw/Oview.aspx?{URL}"
  });
  // 設定初始位置
  let initialPos = new window.GeoPoint(
    121.2347878442796,
    23.427553934089445,
    465850.0013822634
  );
  let initialV = new window.Geo3DPoint(0, 0, -1);
  let initialUp = new window.Geo3DPoint(0, 1, 0);
  let initialCamera = new window.ov.Camera(initialPos, initialV, initialUp);
  terrainview.gotoCamera(initialCamera, false);

  // 新增天氣物件
  weather = terrainview.getModule("weather");
  weather.proxy = "https://sample.pilotgaea.com.tw/weather.ashx?"; // 設定代理伺服器位置
  // weather.authorization = ""; // 填入氣象局API Key


  // 新增時間軸物件
  widgetTimeline = new window.ov.Widget.Timeline({
    view: terrainview,
    style: { left: "10%", width: "88%" },
    isRepeat: true
  });

  // 新增時間軸撥放器物件
  widgetTimelinePlayer = new window.ov.Widget.TimelinePlayer({
    view: terrainview,
    timeline: widgetTimeline,
    playSpeed: 1500.0
  });
}

document.getElementById("HistoryStart").addEventListener("click", function () {
  weather.authorization = document.getElementById('apiKeyInput').value; //帶入使用者輸入的氣象局API Key 
  let v = parseInt(document.getElementById("limit").value);
  let end = new Date();
  let begin = new Date(end.getTime() - v * 60 * 60 * 1000);
  document.getElementById("HistoryStart").disabled = true;
  document.getElementById("loader").style.display = "block";
  window.ov.UI.Alertify.Notify("請稍後...");
  if (historylayer) {
    removeHistoryLayer(historylayer);
    historylayer = null;
  }
  // 新增雷達回波歷史圖層
  weather.addRadarReflectivityHistoryLayer(
    {
      layername: "weather", // 圖層名稱
      timeFrom: begin, // 開始時間(包含),氣象資料開放平台只有保存十天(10246筆)的資料
      timeTo: end, // 結束時間(包含)
      limit: v * 6, // 限制最多回傳符合條件的最新資料筆數
      offset: 0, // 指定從第幾筆開始回傳
      interval: 10 // 資料間隔(分鐘),氣象資料開放平台的歷史資料間隔為10分鐘,可以設大一點來降低網路流量與系統負載
    },
    function (rtn) {
      if (window.IsString(rtn)) {
        window.ov.UI.Alertify.Error(rtn);
      } else {
        window.ov.UI.Alertify.Notify("完成");
        historylayer = rtn;
        addLayerToTimeline(historylayer, v);
      }

      document.getElementById("loader").style.display = "none";
      document.getElementById("HistoryStart").disabled = false;
    }
  );
});

document.getElementById("HistoryClear").addEventListener("click", function () {
  if (historylayer) {
    removeHistoryLayer(historylayer);
    historylayer = null;
  }
});

function addLayerToTimeline(layer, v) {
  let timespan = layer.playingInfo.TimeSpan;
  widgetTimeline.updateParameter({
    startTime: timespan[0],
    stopTime: timespan[1],
    playSpeed: v * 500.0
  });
  // 回到撥放區間最開頭
  widgetTimeline.toStart();
  // 撥放
  widgetTimelinePlayer.play();
  // weather圖層綁訂時間軸
  widgetTimeline.addLink(
    layer,
    timespan[0].toLocaleString() + "~" + timespan[1].toLocaleString() + " 回波"
  );
}

function removeHistoryLayer(layer) {
  widgetTimelinePlayer.stop();
  widgetTimeline.removeLink(layer);
  widgetTimeline.updateParameter({
    startTime: null,
    stopTime: null
  });
  weather.removeLayer(layer);
  terrainview.updateScreen();
}
Copyright © NCHC 2022 Version:13.0 all right reserved,powered by Gitbook修訂時間: 2024-11-20 13:52:09