iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 18
0
Modern Web

《你的地圖會說話? WebGIS與JavaScript的情感交織》系列 第 18

[7-1] 3D地圖初探 - ArcGIS API for JavaScript

本系列文章已出版實體書籍:
「你的地圖會說話?WebGIS 與 JavaScript 的情感交織」(博碩文化)
WebGIS啟蒙首選✖五家地圖API✖近百個程式範例✖實用簡易口訣✖學習難度分級✖補充ES6小知識

原本這篇預定要介紹ArcGIS API for JavaScript,
但是想想如果繼續介紹點、線、面、圖層套疊等等,
只是換個圖台API,換個寫法,未免無趣。
因此我總是想找一些屬於該API特有的,介紹給大家認識,
找來找去決定來玩玩看3D地圖?!


Dojo框架

ArcGIS API為了簡化開發過程,使用了Dojo框架做為整體架構,起初在3.33版本時dojo最重要的功用為dojo.require,為達到非同步模組化管理,也就是所謂的AMD規範。早期JavaScript尚未有良好的模組化管理系統,隨著程式越寫越龐大,JS分支越來越多,再加上JS非同步的概念,想要讓程式獨立而不依賴瀏覽器DOM的Include,必須靠別的手段去實現,而dojo.require就是一個很好的管理工具。

  • dojo.require

↓ 以HTML include方式載入每個模組,ArcGIS API不使用此方法。

        <script src="https://js.arcgis.com/4.16/esri/map"></script>

↓ 以dojo方式載入模組(舊式寫法)

        dojo.require("esri.map");

↓ ArcGIS API已全面支援AMD,所有模組皆以define()的方式輸出,並以require方式載入。

        require(["esri/map", ... ], function(Map, ... ){ 
            // 在這邊使用輸出的Map或其他模組
        });
  • dojo.ready

↓ 以dojo/ready模組可以讓程式在DOM載入完畢時才觸發,效果同JQ的$(document).ready()

        require(["dojo/ready"], function (ready) {
            ready(function () {
                // DOM載入完畢時觸發
            });
        });
  • dojo.connect

↓ 以dojo/on模組可以為dom元素增加監聽事件。(舊版寫法為dojo.connect)

        require(["esri/map", "dojo/on"], function (Map, on) {
            on(myMap, "load", callback);  // 事件觸發callback函式
        });
  • 3.33版本載入範例

↓ 載入css與js

    <link rel="stylesheet" href="https://js.arcgis.com/3.33/esri/css/esri.css">
    <script src="https://js.arcgis.com/3.33/"></script>

↓ 利用require方式載入底圖模組("esri/basemaps")、地圖模組("esri/map")、dojo.ready模組("dojo/domReady!")。

        require([
            "esri/basemaps",
            "esri/map",
            "dojo/domReady!"
        ], function (esriBasemaps, Map) {
            esriBasemaps.delorme = {  // 設定底圖
                baseMapLayers: [{ url: "https://services.arcgisonline.com/ArcGIS/rest/services/Specialty/DeLorme_World_Base_Map/MapServer" }
                ],
                thumbnailUrl: "https://www.example.com/images/thumbnail_2014-11-25_61051.png",
                title: "Delorme"
            };

            var map = new Map("amap", {  // 初始化地圖
                basemap: "delorme",
                center: [121, 23.5], 
                zoom: 8,
                sliderStyle: "small"
            });
        });

↓ 結果
https://ithelp.ithome.com.tw/upload/images/20201003/20130604s9sJWXAQT5.jpg

MapView & SceneView

然而,ArcGIS API已宣布2022年將會停用3.33版本,全面改用最新的4.16版本。
在新的版本中,新增了View的概念,在使用Map模組初始化地圖後,
還需要把它新建在view中與DOM元素做綁定,
這也代表了一個地圖可以重複使用,並且可以不只綁定在一個dom元素上。
MapView是用來做為2D地圖使用,SceneView則是用來做為3D地圖使用。

↓ 載入ArcGIS API 4.16版本

    <link rel="stylesheet" href="https://js.arcgis.com/4.16/esri/themes/light/main.css" />
    <script src="https://js.arcgis.com/4.16/"></script>

↓ 存放地圖的div

    <div id="amap"></div>
  • MapView

↓ 載入地圖模組("esri/Map")、2D視覺模組("esri/views/MapView")

        require([
            "esri/Map",
            "esri/views/MapView"
        ], function (Map, MapView) {

            var map = new Map({
                basemap: "topo-vector"  // 底圖
            });

            var view = new MapView({
                container: "amap",
                map: map,
                center: [121, 23.5], 
                zoom: 8,
            });
        });

↓ 結果
https://ithelp.ithome.com.tw/upload/images/20201003/20130604p6mOXUU1tT.jpg

  • SceneView

↓ 載入地圖模組("esri/Map")、3D視覺模組("esri/views/SceneView")

        require([
            "esri/Map",
            "esri/views/SceneView",
        ], function (Map, SceneView) {
            var map = new Map({
                basemap: "topo-vector",
                ground: "world-elevation"
            });
            var view = new SceneView({
                container: "amap",
                map: map,
                camera: {
                    position: {
                        x: 121,
                        y: 23.5,
                        z: 18000  // 設定觀看高度(公尺)
                    },
                    tilt: 75
                }
            });
        });

↓ 結果
https://ithelp.ithome.com.tw/upload/images/20201003/20130604s8QO4YUrPm.jpg
讓我們一同眺望中央山脈的雄偉!

  • WebScene

ArcGIS為GIS界大佬ESRI公司所開發,有諸多產品如ArcGIS for Desktop、ArcGIS Online等。如果今天在ArcGIS Online建立地圖,並且加入圖層並做一些修改過後,想要直接在WebGIS上載入,只要透過ArcGIS認證的一組id就可以輕鬆載入啦!

↓ 載入WebScene模組("esri/WebScene"),用以載入ArcGIS Online上面的專案。
這邊用ArcGIS API範例的專案

        require([
            "esri/Map",
            "esri/WebScene",
            "esri/views/SceneView",
        ], function (Map, WebScene, SceneView) {

            const webscene = new WebScene({
                portalItem: {
                    id: "579f97b2f3b94d4a8e48a5f140a6639b"  // 專案id
                }
            });
            console.log(webscene);

            const view = new SceneView({
                container: "amap",
                map: webscene,
                camera: {
                    position: {
                        x: -118.808,
                        y: 33.961,
                        z: 2000 
                    },
                    tilt: 75
                }
            });

↓ 結果
https://ithelp.ithome.com.tw/upload/images/20201003/20130604en438m7yWR.jpg

  • FeatureLayer

用ArcGIS Server發佈的圖層可以藉由FeatureLayer加入3D地圖中。

↓ ArcGIS Server發佈的圖層介面,這邊使用的也是ArcGIS的範例圖層之一
https://ithelp.ithome.com.tw/upload/images/20201003/201306042yeJbiJ5Uz.jpg

↓ 載入FeatureLayer模組("esri/FeatureLayer")

        require([
            "esri/Map",
            "esri/views/SceneView",
            "esri/layers/FeatureLayer"
        ], function (Map, SceneView, FeatureLayer) {

            const map = new Map({
                basemap: "topo-vector",
                ground: "world-elevation"
            });
            const view = new SceneView({
                container: "amap",
                map: map,
                camera: {
                    position: {
                        x: -118.808,
                        y: 33.961,
                        z: 2000 
                    },
                    tilt: 75
                }
            });

            // 點圖層
            const featureLayer = new FeatureLayer({
                url: "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trailheads/FeatureServer/0"
            });

            map.add(featureLayer);

            // 線圖層
            const trailsLayer = new FeatureLayer({
                url:                    "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trails/FeatureServer/0"
            });

            map.add(trailsLayer, 0);

            // 面圖層
            const parksLayer = new FeatureLayer({
                url:                    "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Parks_and_Open_Space/FeatureServer/0"
            });

            map.add(parksLayer, 0);
        });

↓ 結果
https://ithelp.ithome.com.tw/upload/images/20201003/2013060486yfGacQnn.jpg


今天簡單介紹了ArcGIS API從3.33到4.16的演變,
用dojo框架定義模組,並且建立2D、3D地圖,
大家有空可以玩玩看!(不用api key很方便)

然而,dojo.require引入模組的方式要怎麼設定,
要怎麼去定義模組、輸出模組?ES6以後又有什麼語法可以取代require?

明天要講解require.js的使用方式以及ES6 Import!
不要錯過囉!/images/emoticon/emoticon15.gif


上一篇
[6-2] KML & GeoJSON - 以Leaflet KML layer plugin實現
下一篇
[7-2] 實現AMD的require.js 與 ES6 Import/Export 大比拚
系列文
《你的地圖會說話? WebGIS與JavaScript的情感交織》30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言