高德地圖JS API空間數據採集開發入門實驗

準備

準備頁面:

  1. 在頁面添加 JS API 的入口腳本標籤,並將其中「您申請的key值」替換爲您剛剛申請的 key;
    <script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=您申請的key值"></script>

  2. 添加div標籤作爲地圖容器,同時爲該div指定id屬性;
    <div id="container"></div>

  3. 爲地圖容器指定高度、寬度;#container {width:300px; height: 180px; }

  4. 進行移動端開發時,請在head內添加viewport設置,以達到最佳的繪製性能;
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">

  5. 在完成如上準備工作之後便可以開始進行開發工作了,查看快速入門。

加載 JS API

上一節說明的是最基本的同步加載 JS API 的方式,如果您需要異步加載,比如通過appendChild,或者通過require等異步方式來加載,這時需要您需要先準備一個全局的回調函數作爲 JS API 異步加載的回調函數,並將其函數名作爲callback參數添加在 JS API 的引用地址後面,此時要注意,回調函數應該在腳本請求發出之前進行聲明。異步加載方式只有在回調之後,才能開始調用JSAPI的相關接口。比如

 window.onLoad  = function(){
        var map = new AMap.Map('container');
  }
  var url = 'https://webapi.amap.com/maps?v=1.4.15&key=您申請的key值&callback=onLoad';
  var jsapi = doc.createElement('script');
  jsapi.charset = 'utf-8';
  jsapi.src = url;
  document.head.appendChild(jsapi);

JS API 支持多種加載方式,可以順序加載也可以異步加載,同時也可以作爲一般腳本資源被 RequireJS 等前端框架加載。

順序同步加載

之前我們使用的是基本的順序同步加載方式,這種方式下,地圖初始化的代碼要放在 JS API 的腳本標籤之後:

<script src="https://webapi.amap.com/maps?v=1.4.15&key=您申請的key值"></script>
<script type="text/javascript">
    var map = new AMap.Map('container', {
       center:[117.000923,36.675807],
       zoom:11
    });
</script>

異步加載

異步加載指的是爲 JS API 指定加載的回調函數,在 JS API 的主體資源加載完畢之後,將自動調用該回調函數。回調函數應該聲明在 JS API 入口文件引用之前,異步加載可以減少對其他腳本執行的阻塞,HTTPS 下我們也建議使用異步方式:

<script type="text/javascript">
    window.init = function(){
        var map = new AMap.Map('container', {
           center:[117.000923,36.675807],
           zoom:11
        });
    }
</script>
<script src="https://webapi.amap.com/maps?v=1.4.15&key=您申請的key值&callback=init"></script>

或者

window.onLoad  = function(){
    var map = new AMap.Map('container');
}
var url = 'https://webapi.amap.com/maps?v=1.4.15&key=您申請的key值&callback=onLoad';
var jsapi = document.createElement('script');
jsapi.charset = 'utf-8';
jsapi.src = url;
document.head.appendChild(jsapi);

也可以使用RequireJS 等加載,點這裏瞭解更多,在此不一一贅述。

快速上手

按照「準備」篇完成頁面準備工作之後就可以真正開始地圖的開發工作了。本篇帶您快速瞭解:地圖、圖層、點標記、矢量圖形、信息窗體、事件的最基本使用方法。

HELLO,AMAP!


簡單創建一個地圖只需要一行代碼,構造參數中的`container`爲準備階段添加的地圖容器的`id`:
    var map = new AMap.Map('container');

創建的同時可以給地圖設置中心點、級別、顯示模式、自定義樣式等屬性:

   var map = new AMap.Map('container', {
        zoom:11,//級別
        center: [116.397428, 39.90923],//中心點座標
        viewMode:'3D'//使用3D視圖
    });

圖層


默認情況下,地圖只顯示標準底圖,如需要疊加別的圖層,可以通過`map.add`方法添加圖層:

    var map = new AMap.Map('container', {
        resizeEnable: true,
        center: [116.397428, 39.90923],
        zoom: 13
    });
    //實時路況圖層
    var trafficLayer = new AMap.TileLayer.Traffic({
        zIndex: 10
    });
    map.add(trafficLayer);//添加圖層到地圖

也可以在地圖初始化的時候通過layers屬性爲地圖設置多個圖層:

    var map = new AMap.Map('container', {
        center: [116.397428, 39.90923],
        layers: [//使用多個圖層
            new AMap.TileLayer.Satellite(),
            new AMap.TileLayer.RoadNet()
        ],
        zooms: [4,18],//設置地圖級別範圍
        zoom: 13
    });

地圖 JS API 提供了標準、衛星、路網、路況、建築等多個官方圖層,同時也提供了加載第三方WMS、WMTS、XYZ等標準圖層的接口,也提供了把一般的圖片、Canvas、視頻、熱力等作爲圖層的能力,查看圖層相關教程

點標記與矢量圖形

JS API 提供了在地圖之上繪製覆蓋物的能力,比如點標記 Marker、文本標記 Text、圓點標記 CircleMarker。

添加點標記的方法非常簡單,比如添加一個默認樣式的Marker:

    var marker = new AMap.Marker({
        position:[116.39, 39.9]//位置
    })
    map.add(marker);//添加到地圖

移除的方法如下:

    map.remove(marker)

查看點標記相關教程

也提供了繪製圓Circle、折線 Polyline、多邊形 Polygon、橢圓 Ellipse、矩形 Rectangle、貝瑟爾曲線 BesizerCurve等矢量圖形的能力,比如添加折線:

  var lineArr = [
        [116.368904, 39.913423],
        [116.382122, 39.901176],
        [116.387271, 39.912501],
        [116.398258, 39.904600]
    ];
    var polyline = new AMap.Polyline({
        path: lineArr,          //設置線覆蓋物路徑
        strokeColor: "#3366FF", //線顏色
        strokeWeight: 5,        //線寬
        strokeStyle: "solid",   //線樣式
    });
    map.add(polyline);

查看矢量圖形關教程

事件功能與信息窗體

JS API 提供的Map、點標記、矢量圖形的實例均支持事件,鼠標或者觸摸操作均會觸發相應的事件。我們通過給點標記綁定click事件來簡單瞭解事件系統信息窗體的基本使用:

     var infoWindow = new AMap.InfoWindow({ //創建信息窗體
        isCustom: true,  //使用自定義窗體
        content:'<div>信息窗體</div>', //信息窗體的內容可以是任意html片段
        offset: new AMap.Pixel(16, -45)
    });
    var onMarkerClick  =  function(e) {
        infoWindow.open(map, e.target.getPosition());//打開信息窗體
        //e.target就是被點擊的Marker
    } 
    var marker = new AMap.Marker({
         position: [116.481181, 39.989792]
    })
    map.add(marker);
    marker.on('click',onMarkerClick);//綁定click事件

插件的使用

JS API 提供了衆多的插件功能,這些功能不會主動隨着 JSAPI 主體資源下發,需要引入之後才能使用這些插件的功能。這些功能包括:

  • 服務類,如:POI搜索 PlaceSearch、輸入提示 AutoComplete、路線規劃 Driving/Walker/Transfer/Riding/Truck、地理編碼 Geocoder、公交線路 LineSearch、公交站點 StationSearch、天氣查詢 Weather等;
  • 地圖控件,如:縮放工具條 ToolBar、比例尺 Scale、定位按鈕 Geolocation等;
  • 矢量圖形編輯工具,如折線/多邊形編輯器 PolyEditor、圓形編輯器 CircleEditor等;
  • 工具類,如鼠標繪製工具 MouseTool、測距工具 RangingTool等。

插件的使用流程


使用插件的功能通常需要三個步驟:
  1. 引入插件,支持按需異步加載和同步加載,可同時引入多個插件,見「插件的引入」;
  2. 創建插件實例,非特殊情況需避免重複創建多個實例,複用同一個實例即可;
  3. 調用實例的方法,使用相關功能。

插件的引入


異步加載插件

異步加載指的是在 JS API 加載完成之後,在需要使用到某個插件的時候,通過AMap.plugin方法按需引入插件,在plugin回調之後使用插件功能。

<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=您申請的key值"></script> 
<script type="text/javascript" >
    var map = new AMap.Map('container',{
        zoom:12,
        center:[116.39,39.9]
    });
    AMap.plugin('AMap.ToolBar',function(){//異步加載插件
        var toolbar = new AMap.ToolBar();
        map.addControl(toolbar);
    });
</script>

異步加載多個插件

AMap.plugin的第一個參數使用數組即可同時加載引入多個插件。

  AMap.plugin(['AMap.ToolBar','AMap.Driving'],function(){//異步同時加載多個插件
      var toolbar = new AMap.ToolBar();
      map.addControl(toolbar);
      var driving = new AMap.Driving();//駕車路線規劃
      driving.search(/*參數*/)
  });

同步加載插件

如果希望和 JS API 的主體同步加載某些插件,而不是異步加載,可以在 JS API 的入口地址中添加plugin參數,將需要使用的一個或者多個插件的名稱作爲參數即可,這種用法在 JS API 加載完畢之後便可直接使用插件功能了。

<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=您申請的key值&plugin=AMap.ToolBar"></script> 
<script type="text/javascript" >
    var map = new AMap.Map('mapContainer',{
        zoom:12,
        center:[116.39,39.9]
    });
    var toolbar = new AMap.ToolBar();
    map.plugin(toolbar);
</script>

同步加載多個插件

需要加載多個插件時,plugin參數中的插件名稱之間以逗號分割。

<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=您申請的key值&plugin=AMap.ToolBar,AMap.Driving"></script> 
<script type="text/javascript" >
    var map = new AMap.Map('mapContainer',{
        zoom:12,
        center:[116.39,39.9]
    });
    var toolbar = new AMap.ToolBar();
    map.plugin(toolbar);
    var driving = new AMap.Driving();
    driving.search(/*參數*/)
</script>

地圖組成與名詞解釋

JS API 地圖組成結構

在這裏插入圖片描述
使用高德地圖 JS API 創建的地圖通常由這幾部分組成:

地圖容器 Container

即在準備階段所創建的指定了id的div對象,這個div將作爲承載所有圖層、點標記、矢量圖形、控件的容器。

圖層 Layers

圖層是指能夠在視覺上覆蓋一定地圖範圍,用來描述全部或者部分現實世界區域內的地圖要素的抽象概念,一幅地圖通常由一個或者多個圖層組成。如上圖中處於整個地圖容器最下方的二維矢量圖層和實施交通圖層。

高德地圖 JS API 即提供了標準圖層、衛星圖層、路網圖層、路況圖層等官方標準圖層接口,又提供了加載其他廠商發佈的標準地圖服務的圖層接口,還提供了加載開發者自己的圖片、Canvas、視頻、熱力數據的圖層接口。同時也深度開放了可以自定義繪製方法的自定義圖層接口。

矢量圖形 Vector Overlays

矢量圖形,一般覆蓋於底圖圖層之上,通過矢量的方式(路徑或者實際大小)來描述其形狀,用幾何的方式來展示真實的地圖要素,會隨着地圖縮放而發生視覺大小的變化,但其代表的實際路徑或範圍不變,如上圖中紅框內的折線、圓、多邊形等。

除了圖中的折線、圓、多邊形之外,JS API 還提供了矩形、橢圓、貝瑟爾曲線等常用的矢量圖形。3D 視圖下的 Mesh、Prism 棱柱、MeshLine 也可以看做是一些特殊的矢量圖形。

點標記 Markers

點標記是用來標示某個位置點信息的一種地圖要素,覆蓋於圖層之上。如圖中藍色方框中的兩個點狀要素。其在屏幕上的位置會隨着地圖的縮放和中心變化而發生改變,但是會與圖層內的要素保持相對靜止。

普通的點標記 (即 Marker ) ,支持將自定義圖標和DOM元素作爲展示內容。除了 Marker 之外爲了滿足不同的場景,JS API 另外提供了豐富的點標記類型,比如圓點標記 (CircleMarker) 、文本標記 (Text)、靈活點標記 (ElasticMarker) 。同時我們提供了海量點(MassMarks)、點聚合(MarkerCluster)來滿足大量點標記的展示需求。

地圖控件 Map Controls

控件浮在所有圖層和地圖要素之上,用於滿足一定的交互或提示功能。一般相對於地圖容器靜止,不隨着地圖縮放和中心變化而發生位置的變化。如上圖中綠色方框中的比例尺和級別控件。

常用名詞

插件 Plugins

插件是獨立於JS API 地圖核心模塊之外的一些功能,比如服務類、繪製工具、矢量圖形編輯工具、點聚合、熱力圖等。這些插件不會主動隨 JS API的主體資源的加載而下發,使用之前需要提前引入,詳見插件的使用

地圖級別 ZoomLevel

級別與地圖的比例尺成正比,每增大一級,地圖的比例尺也增大一倍,地圖顯示的越詳細。Web地圖的最小級別通常爲3級,最大級別各家略有不同,高德地圖 JS API 目前最大級別爲 20 級。

經緯度 LngLat

座標通常指經緯度座標,高德地圖的座標範圍大致爲:東西經180度(-180——180,西半球爲負,東半球爲正),南北緯85度(-85——85,北半球爲正,南半球爲負)。

底圖 BaseLayer

嚴格意義上,底圖指處於所有圖層和圖形最下方的一個圖層,通常不透明。可以是單一圖層,比如官方標準圖層,也可以是圖層組合,比圖衛星圖層和路網圖層組合。

地圖要素 Map Features

嚴格意義的地圖要素指的是展示在地圖上的地理要素,包括道路、區域面、建築、POI 標註、路名等。開發者自定義的點標記、矢量圖形也可以看做是一種地圖要素。

標註 Labels

我們習慣將底圖上自帶的標示一定信息的文字或圖標稱爲標註,比如 POI 標註,道路名稱標註等。

地圖平面像素座標 Plane Coordinates

地圖平面像素座標指投影爲平面之後的地圖上的平面像素座標,高德地圖使用的Web墨卡託投影,在3級時,平面座標範圍爲橫縱0-256* 2的3次方 像素,每級別擴大一倍,即第n級的平面座標範圍爲 0-256*2 的 n 次方 像素。

投影 Projection

地圖投影指的是將地球球面的經緯度座標映射到地圖平面座標的變換和映射關係。高德地圖使用 Web 墨卡託投影,即採用 EPSG:3857 座標系統。

三維空間座標 3D Coordinates

三維空間座標是在 3D 地圖模式下的世界座標,由 x、y、z 三個緯度組成。三維空間座標通常用於描述 Object3D 類型的幾何形體。

着手開發一個html頁面

地圖顯示

var map = new AMap.Map('container', {
        resizeEnable: true, //是否監控地圖容器尺寸變化
        zoom:11, //初始化地圖層級
        center: [116.397428, 39.90923] //初始化地圖中心點
    });

參見代碼

給地圖增加控件

實際編寫過程中並沒有使用這麼多控件,鼠標的滾輪功能已經滿足大部分需求。
參見代碼

輸入提示後查詢

//輸入提示
    var autoOptions = {
        input: "tipinput"
    };
    var auto = new AMap.Autocomplete(autoOptions);
    var placeSearch = new AMap.PlaceSearch({
        map: map
    });  //構造地點查詢類
    AMap.event.addListener(auto, "select", select);//註冊監聽,當選中某條記錄時會觸發
    function select(e) {
        placeSearch.setCity(e.poi.adcode);
        placeSearch.search(e.poi.name);  //關鍵字查詢查詢
    }

參見代碼

周邊搜索

AMap.service(["AMap.PlaceSearch"], function() {
        // 構造地點查詢類
        var placeSearch = new AMap.PlaceSearch({
            type: '餐飲服務', // 興趣點類別
            pageSize: 5, // 單頁顯示結果條數
            pageIndex: 1, // 頁碼
            city: "010", // 興趣點城市
            citylimit: true,  //是否強制限制在設置的城市內搜索
            map: map, // 展現結果的地圖實例
            panel: "panel", // 結果列表將在此容器中進行展示。
            autoFitView: true // 是否自動調整地圖視野使繪製的 Marker點都處於視口的可見範圍
        });

        var cpoint = [116.405467, 39.907761]; //中心點座標
        placeSearch.searchNearBy('', cpoint, 200, function(status, result) {

        });
    });

參見代碼

多邊形搜索

AMap.service(["AMap.PlaceSearch"], function() {
        var placeSearch = new AMap.PlaceSearch({ //構造地點查詢類
            pageSize: 5, // 單頁顯示結果條數
            pageIndex: 1, // 頁碼
            city: "010", // 興趣點城市
            citylimit: true,  //是否強制限制在設置的城市內搜索
            map: map, // 展現結果的地圖實例
            panel: "result", // 結果列表將在此容器中進行展示。
            autoFitView: true // 是否自動調整地圖視野使繪製的 Marker點都處於視口的可見範圍
        });
        //多邊形查
        var polygonArr = [//多邊形覆蓋物節點座標數組
            [116.403322, 39.920255],
            [116.410703, 39.897555],
            [116.402292, 39.892353],
            [116.389846, 39.891365]
        ];
        var polygon = new AMap.Polygon({
            path: polygonArr,//設置多邊形邊界路徑
            strokeColor: "#FF33FF", //線顏色
            strokeOpacity: 0.2, //線透明度
            strokeWeight: 3,    //線寬
            fillColor: "#1791fc", //填充色
            fillOpacity: 0.35//填充透明度
        });
        placeSearch.searchInBounds('酒店', polygon);
    });

從這裏不難看出來,多邊形檢索與周邊檢索非常類似,當開發出來周邊搜索,可類似開發多邊形搜索功能。
參見代碼

功能整合

瞭解了上述幾個簡單功能之後,開始嘗試將三個功能整合到一個html頁面上。

  1. 輸入文本後搜索的html頁面作爲開發基礎

  2. 增加周邊搜索小窗口按鈕

  3. 對上述按鈕進行事件綁定,實現點擊自動縮放到特定周邊。詳見:周邊搜索

  4. 編輯周邊搜索的默認圖形,使得周邊搜索更加靈活。 圓的編輯代碼圓的繪製和編輯

  5. 在此基礎上,也可以增加清除覆蓋物的實現。這使得當多次使用周邊查詢時頁面仍能保持較爲整潔的良好觀感。有關覆蓋物的清除方法可以參見:覆蓋物

整合後所有的代碼如下:

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
    <title>輸入提示後查詢</title>
    <link rel="stylesheet" href="https://cache.amap.com/lbs/static/main1119.css"/>
    <link rel="stylesheet" href="https://a.amap.com/jsapi_demos/static/demo-center/css/demo-center.css" />
    <script src="https://webapi.amap.com/maps?v=1.4.15&key=YourKeyValue&plugin=AMap.CircleEditor"></script>
    <script src="https://a.amap.com/jsapi_demos/static/demo-center/js/demoutils.js"></script>
    <script src="https://cache.amap.com/lbs/static/es5.min.js"></script>
    <script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=e1e9cc8dd1c2ea38bb2d5c885eccc357&plugin=AMap.Autocomplete,AMap.PlaceSearch"></script>
    <!--<script type="text/javascript" src="https://cache.amap.com/lbs/static/addToolbar.js"></script>-->
    <style>
        html,
        body,
        #container {
            width: 100%;
            height: 100%;
        }
        label {
            width: 55px;
            height: 26px;
            line-height: 26px;
            margin-bottom: 0;
        }
        button.btn {
            width: 80px;
            margin-left: 3px;
            margin-right: 3px;
            margin-top: 3px;
            margin-bottom: 3px;
        }
        #panel {
            position: fixed;
            background-color: white;
            max-height: 90%;
            overflow-y: auto;
            top: 10px;
            right: 10px;
            width: 280px;
            border-bottom: solid 1px silver;
        }
        #myPageTop{
        }
    </style>

</head>
<body>
<div id="container" ></div>
<div id="panel"></div>

<div id="myPageTop" style="width: 24rem; ">
    <h4>請輸入查找</h4>
    <div class="input-item">
        <input id="tipinput" style="margin-right:1rem;"/>
    </div>
</div>

<div class="input-card" style="width:45rem;">
    <h4>POI查詢/搜索服務</h4>
    <div class="input-item">
        <label>功能:</label>
        <button class="btn" id="search-nearby"> <!--style="margin-right:1rem;"-->周邊查詢</button>
        <button class="btn" id="start-edit"> <!--style="margin-bottom: 5px"-->開始編輯</button>
        <button class="btn" onclick="circleEditor.close()">結束編輯</button>
        <button class="btn" id="removeAllOverlay" ><!--style="margin-bottom: 5px"-->清除所有</button>
    </div>
</div>
<script type="text/javascript">

    // 定義全局變量
    var cpoint = [116.405467, 39.907761];
    var lng;
    var lat;
    var radius = 200;

    //地圖加載
    var map = new AMap.Map("container", {
        resizeEnable: true
    });
    //輸入提示
    var autoOptions = {
        input: "tipinput"
    };
    var auto = new AMap.Autocomplete(autoOptions);
    var placeSearch = new AMap.PlaceSearch({
        map: map
    });  //構造地點查詢類
    AMap.event.addListener(auto, "select", select);//註冊監聽,當選中某條記錄時會觸發
    function select(e) {
        placeSearch.setCity(e.poi.adcode);
        placeSearch.search(e.poi.name);  //關鍵字查詢查詢

    }

    // 事件綁定:周邊搜索
    document.querySelector("#search-nearby").onclick = function() {
        AMap.service(["AMap.PlaceSearch"], function() {
            // 構造地點查詢類
            var placeSearch = new AMap.PlaceSearch({
                //type: '餐飲服務', // 興趣點類別
                type: '汽車服務|汽車銷售|汽車維修|摩托車服務|餐飲服務|購物服務|生活服務|體育休閒服務|\n' +
                '\n' +
                '醫療保健服務|住宿服務|風景名勝|商務住宅|政府機構及社會團體|科教文化服務|\n' +
                '\n' +
                '交通設施服務|金融保險服務|公司企業|道路附屬設施|地名地址信息|公共設施',
                pageSize: 5, // 單頁顯示結果條數
                pageIndex: 1, // 頁碼
                city: "010", // 興趣點城市
                citylimit: true,  //是否強制限制在設置的城市內搜索
                map: map, // 展現結果的地圖實例
                panel: "panel", // 結果列表將在此容器中進行展示。
                autoFitView: true // 是否自動調整地圖視野使繪製的 Marker點都處於視口的可見範圍
            });

            //cpoint = [lng,lat]; //中心點座標,要傳入參數。

            //var cpoint = [116.433320, 39.900255]; //中心點座標,抱歉,未搜索到有效的結果
            placeSearch.searchNearBy('', cpoint, radius, function(status, result) {

            });
        });
    };

    document.querySelector("#start-edit").onclick = function () {
        var circle = new AMap.Circle({
            map: map,
            center:new AMap.LngLat("116.40332221984863","39.90025505675715"),// 116.405467, 39.907761
            radius:1000,
            strokeColor: "#F33",
            strokeOpacity: 1,
            strokeWeight: 3,
            fillColor: "ee2200",
            fillOpacity: 0.35
        });

        map.plugin(["AMap.CircleEditor"],function(){
            circleEditor = new AMap.CircleEditor(map,circle);
            circleEditor.open();
        });


        circleEditor.on('move', function(event) {
            log.info('觸發事件:move')
        })

        circleEditor.on('adjust', function(event) {
            log.info('觸發事件:adjust')
        })

        circleEditor.on('end', function(event) {
            log.info('觸發事件: end')
            lng = circle.getCenter().getLng();
            lat = circle.getCenter().getLat();
            radius = circle.getRadius();
            cpoint = [lng,lat];
            // event.target 即爲編輯後的圓形對象
        })

    };

    function removeAllOverlay(){

        // 清除地圖上所有添加的覆蓋物
        map.clearMap();
    }

    // 綁定移除事件
    document.getElementById("removeAllOverlay").onclick = removeAllOverlay;

</script>
</body>
</html>

將poi數據寫入數據庫

使用access創建數據庫,並使用IE瀏覽器預覽(因爲要用到基於IE內核瀏覽器支持的ActiveX插件)。其他瀏覽器暫不支持ActiveX插件。

新建數據庫

  1. 空數據庫,命名爲poiData;
  2. 新建表:poi
  3. 添加字段:NamepoiIDLngLat,數據類型都是短文本
  4. 保存爲2002-2003數據庫版本,路徑filePath

連接並修改數據庫函數

function addPOIData(strName, strId, strLongitude, strLatitude) {
    //創建數據庫連接對象
    var conn = new ActiveXObject("ADODB.Connection");
    //創建數據集對象
    var rs = new ActiveXObject("ADODB.Recordset");

    var connectionString = "DBQ=filePath.mdb;DRIVER={Microsoft Access Driver (*.mdb)};";
    
    console.log(connectionString);
    conn.open(connectionString);
    var sql = "insert into poi(Name,poiID,Lng,Lat) values('" + strName + "','" + strId + "','" + strLongitude + "','" + strLatitude + "')";
    try {
        conn.execute(sql);
        //關閉記錄集
        rs.close();
        //關閉數據庫連接
        conn.close();
    }
    catch (e) {
        document.write(e.description);
    }
}

將poi部分屬性寫入數據庫

根據搜索結果添加marker爲例,把其中的數據寫入到數據庫:

  1. 找到獲取poi對象的地方:
placeSearch.search('東方明珠', function (status, result) {
       // 查詢成功時,result即對應匹配的POI信息
       console.log(result)
       var pois = result.poiList.pois;
        for(var i = 0; i < pois.length; i++){
            var poi = pois[i];
            var marker = [];
            marker[i] = new AMap.Marker({
                position: poi.location,   // 經緯度對象,也可以是經緯度構成的一維數組[116.39, 39.9]
                title: poi.name
            });
            // 將創建的點標記添加到已有的地圖實例:
            map.add(marker[i]);
        }
        map.setFitView();

    })
  1. 在獲取到poi對象之後,使用addPOIData函數:
map.add(marker[i]);
addPOIData(poi.name,poi.id,poi.location.lng,poi.location.lat);
  1. 打開測試html頁面是否可行。當查詢到數據庫的數據如下:
ID Name poiID Lng Lat
1 東方明珠廣播電視塔 B00150F6D6 121.499717 31.239702
2 東方明珠廣播電視塔(公交站) BV10385979 121.50161 31.239862
3 陸家嘴(地鐵站) BV10029743 121.502262 31.238195
4 東方明珠 B0FFL7YY8J 121.699108 31.187925
5 東方明珠 B0FFL7L39N 121.657356 31.584515
6 東方明珠 B0FFLDUR2A 121.412119 31.173262
7 東方明珠公園 B0FFFS16ZK 121.500127 31.241103
8 東方明珠廣播電視塔(1門) B00155DLW1 121.500617 31.23885
9 東方明珠-城市廣場 B0FFG4JZTG 121.499649 31.239729
10 東方明珠廣播電視塔(8號門) B00155R4RT 121.500861 31.239404

則說明數據添加成功了。

在打開ie的時候如果遇到ADO警告(通常是很多個彈窗警告),可以參見該鏈接解決。

周邊搜索、關鍵字搜索的數據存儲

  1. 找到關鍵字搜索函數入口:
placeSearch.search(e.poi.name,function (status, result){})

修改函數:

placeSearch.setCity(e.poi.adcode);
	//關鍵字查詢
	placeSearch.search(e.poi.name,function (status, result) {
	    console.log(result);
	    var pois = result.poiList.pois;
	    for(var i = 0; i < pois.length; i++){
	        var poi = pois[i];
	        var marker = [];
	        marker[i]=new AMap.Marker({
	            position: poi.location,
	            title: poi.name
	        });
	        map.add(marker[i]);
	        addPOIData(poi.name,poi.id,poi.location.lng,poi.location.lat);
	    }
	    map.setFitView();
	});

並在獲取到poi對象之後添加addPOIData函數,測試是否可用:ie打開該html頁面,輸入搜索:重慶。選擇重慶市,等待地圖頁面加載出來。此時刷新poi表見到如下數據:

ID Name poiID Lng Lat
176 重慶市 B00178WI1P 106.550464 29.563761
177 重慶市中心 B00178TUGP 106.551294 29.562943
178 重慶市人民政府 B001702338 106.550483 29.563707
179 重慶市渝中區瑞天路61-8 B0FFKTRMRS 106.50242 29.553818
180 重慶市渝中區健康路滷店王燒臘 B0FFKQZZVC 106.543084 29.552855
181 重慶市包協 B001709UXJ 106.561941 29.555964
182 重慶市婦聯 B001783SH3 106.54805 29.564651
183 中國共產黨重慶市委員會 B00170CT3Z 106.548386 29.563538
184 重慶市科學技術協會 B00170L88M 106.565265 29.561184
185 重慶市疾病預防控制中心(上肖家壪) B0017098ZK 106.527192 29.542505
說明函數可用。 同樣地,爲“周邊搜索”功能添加該函數。入口函數:
placeSearch.searchNearBy('', cpoint, 200, function(status, result) {

	});

爲其添加對應函數

placeSearch.searchNearBy('', cpoint, radius, function(status, result) {
    // 查詢成功時,result即對應匹配的POI信息
    console.log(result)
    var pois = result.poiList.pois;
    for(var i = 0; i < pois.length; i++){
        var poi = pois[i];
        var marker = [];
        marker[i] = new AMap.Marker({
            position: poi.location,   
            // 經緯度對象,也可以是經緯度構成的一維數組[116.39, 39.9]
            title: poi.name
        });
        // 將創建的點標記添加到已有的地圖實例:
        map.add(marker[i]);
        addPOIData(poi.name, poi.id, poi.location.lng, poi.location.lat);
    }
    map.setFitView();

});

同樣對其功能進行測試。周邊搜索定位到北京。傳入的座標爲:[116.405467, 39.907761]

ID Name poiID Lng Lat
186 菖蒲河沿 B0FFGZCBUD 116.404956 39.908786
187 公共廁所 B000A83BHO 116.405332 39.908872
188 北庫司衚衕1號 B0FFI7883D 116.404825 39.909184
189 歐美同學會(菖蒲河沿) B000AA21AN 116.406377 39.9091
190 南河沿大街與菖蒲河沿交叉口 B0FFI8LC5Z 116.406674 39.908958

同樣地,編輯圓形之後也可以進行搜索。

搜索功能改進與完善

移動塊

以上html佈局中,不同功能之間相互遮擋。給出下面函數使得div可移動。

function dragDiv(id) {
    var Drag = document.getElementById(id);
    Drag.onmousedown = function (ev) {
        var ev = event || window.event;
        event.stopPropagation();
        var disX = ev.clientX - Drag.offsetLeft;
        var disY = ev.clientY - Drag.offsetTop;
        document.onmousemove = function (ev2) {
            var ev = event || window.event;
            Drag.style.left = ev.clientX - disX + "px";
            Drag.style.top = ev.clientY - disY + "px";
            Drag.style.cursor = "move";
        };
    };
    Drag.onmouseup = function (ev) {
        document.onmousemove = null;
        this.style.cursor = "default";
    };
}

自定義畫圓及繪製其他覆蓋物的搜索形式

圓形搜索

之前的案例中,覆蓋物都是給定之後進行修改,不可自定義覆蓋物。參考繪製矢量圖形,進行圓的繪製。

var mouseTool = new AMap.MouseTool(map);
function drawCircle () {
	mouseTool.circle({
	   strokeColor: "#FF33FF",
	   strokeOpacity: 1,
	   strokeWeight: 6,
	   strokeOpacity: 0.2,
	   fillColor: '#1791fc',
	   fillOpacity: 0.4,
	   strokeStyle: 'solid'
	   // 線樣式還支持 'dashed'
	   // strokeDasharray: [30,10],
	});
	// mouseTool.circle();
    }
mouseTool.on('draw', function(event) {
	// event.obj 爲繪製出來的覆蓋物對象
	log.info('覆蓋物對象繪製完成');
    })

由於繪製的對象是圓,那麼event.obj.CLASS_NAME就是AMap.Circle。那麼可以獲取對應的參數進行相應設置。

cpoint = event.obj.getCenter();
lng = event.obj.getCenter().getLng();
lat = event.obj.getCenter().getLat();
radius = event.obj.getRadius();

多邊形搜索

按照前面的思路,開發多邊形搜索功能。參照多邊形搜索

var polygonArr = [//多邊形覆蓋物節點座標數組
     [116.403322, 39.920255],
     [116.410703, 39.897555],
     [116.402292, 39.892353],
     [116.389846, 39.891365]
	 ];
var polygon = new AMap.Polygon({
     path: polygonArr,//設置多邊形邊界路徑
     strokeColor: "#FF33FF", //線顏色
     strokeOpacity: 0.2, //線透明度
     strokeWeight: 3,    //線寬
     fillColor: "#1791fc", //填充色
     fillOpacity: 0.35//填充透明度
	 });
placeSearch.searchInBounds('酒店', polygon);

參考繪製矢量圖形,將默認的多邊形修改爲繪製多邊形,並獲取動態座標。如果不知道polygon有哪些屬性,可以查看覆蓋物-參考手冊找到polygon對應的屬性列表。在方法一欄中找到getPath()返回Array類型:獲取折線路徑的節點數組。說明:其中lat和lng是經緯度參數。

function drawPolygon () {
	mouseTool.polygon({
	    strokeColor: "#FF33FF",
	    strokeOpacity: 1,
	    strokeWeight: 6,
	    strokeOpacity: 0.2,
	    fillColor: '#1791fc',
	    fillOpacity: 0.4,
	    // 線樣式還支持 'dashed'
	    strokeStyle: "solid",
	    // strokeStyle是dashed時有效
	    // strokeDasharray: [30,10],
		})
    }
mouseTool.on('draw', function(event) {
    // event.obj 爲繪製出來的覆蓋物對象
    log.info('覆蓋物對象繪製完成');
    polygonArr= event.obj.getPath();
})

將上述polygonArr替換爲動態路徑,然後再定義全局變量polygonArr即可。測試代碼搜索成功後,給placeSearch.searchInBounds('酒店', polygon);增加回調函數。參照周邊搜索及其修改後的代碼。

function(status, result) {
	// 查詢成功時,result即對應匹配的POI信息
	console.log(result)
	var pois = result.poiList.pois;
	for(var i = 0; i < pois.length; i++){
	    var poi = pois[i];
	    var marker = [];
	    marker[i] = new AMap.Marker({
	        position: poi.location,   // 經緯度對象,也可以是經緯度構成的一維數組[116.39, 39.9]
	        title: poi.name
	    	});
	    // 將創建的點標記添加到已有的地圖實例:
	    map.add(marker[i]);
	    addPOIData(poi.name, poi.id, poi.location.lng, poi.location.lat);
		}
	map.setFitView();
	
	}

測試:用ie瀏覽器打開,框選廣州的一處地方,搜索並刷新數據庫。

ID Name poiID Lng Lat
191 微八連鎖酒店(廣州西村分店) B00140WAL7 113.239592 23.140388
192 東盈快捷酒店 B0FFGOFIHG 113.545177 23.110201
193 原景商務酒店(廣州北京路紀念堂地鐵站店) B00141JVYF 113.262521 23.131277
194 廣州斯維登服務公寓(洛溪漁人碼頭) B0FFG1AB92 113.296751 23.048226
195 盈豐源酒店(會展中心店) B00140W1Y4 113.280034 23.102697

可見多邊形搜索功能也開發完成了。

沿線搜索

需求:通過在地圖上畫Polyline折線覆蓋物,對覆蓋物區域進行搜索。並將數據存儲到數據庫。

關於Polyline屬性詳見

首先,增加繪製折線的函數:參考繪製矢量圖形,進行折線繪製測試,並獲取到覆蓋物對象爲:AMap.Polyline,這與我們的預期一致。

function drawPolyline () {
    mouseTool.polyline({
        strokeColor: "#3366FF",
        strokeOpacity: 1,
        strokeWeight: 6,
        // 線樣式還支持 'dashed'
        strokeStyle: "solid",
        // strokeStyle是dashed時有效
        // strokeDasharray: [10, 5],
    })
}
mouseTool.on('draw', function(event) {
    // event.obj 爲繪製出來的覆蓋物對象
    log.info('覆蓋物對象繪製完成')
	
	polylineArr = event.obj.getPath();

})

高德地圖沒有對Polyline進行搜索的函數。先查找Polyline屬性。通過查看覆蓋物-參考手冊,發現方法getPath( ) 返回Array 獲取折線路徑的節點數組。其中lat和lng是經緯度參數。以及方法getBounds( )返回 Bounds 獲取當前折線的矩形範圍對象。

所謂“沿線搜索”,本質上是把折線轉化爲具有較小寬度的長方形條帶,再對這個帶狀區域進行多邊形搜索。以上兩個方法都能獲取到折線相關信息,這裏只需要“沿線搜索”,所以獲取getPath()即可(見上述代碼)。首先把獲取到的折線座標轉化爲帶狀區域多邊形座標,然後將帶狀座標通過setPath方法設置到Polyline對象即可。剩餘步驟類似於多邊形搜索。但這種方法,將折線數組轉化爲帶狀圖形數組的難度比較大。另一種沿線搜索的策略是:先獲取折線路徑的路線規劃,再從路線規劃中獲取相關poi信息。如此一來,沿線搜索就變成了取折線折點的點搜索。路線規劃參考

首先找到路線規劃相關的函數:

var driving = new AMap.Driving(drivingOption)

    // 根據起終點經緯度規劃駕車導航路線
    driving.search(new AMap.LngLat(116.379028, 39.865042), new AMap.LngLat(116.427281, 39.903719), function(status, result) {
        // result 即是對應的駕車導航信息,相關數據結構文檔請參考  
        //https://lbs.amap.com/api/javascript-api/reference/route-search#m_DrivingResult
        if (status === 'complete') {
            log.success('繪製駕車路線完成')
        } else {
            log.error('獲取駕車數據失敗:' + result)
        }
    });

接着查看回傳參數result的相關屬性:DrivingResult對象,發現有start(起點),end(終點),waypoints(途經點,最多支持不大於16個途經點)三個屬性可供使用,它們都屬於poi類型。所以仿照上述的代碼,添加marker並保存數據:

function drivingSearch() {
    driving.search(path[0],path[path.length-1 ],{waypoints:path},function (status, result) {
        if (status === 'complete') {
            log.success('繪製駕車路線完成')
        } else {
            log.error('獲取駕車數據失敗:' + result)
        }
        
        // var pois = result.poiList.pois;
        var pois = [];
        pois.push(result.start);
        for(i=0;i<result.waypoints.length;i++)
        pois.push(result.waypoints[i]);
        pois.push(result.end);
        for(var i = 0; i < pois.length; i++){
            var poi = pois[i];
            var marker = [];
            marker[i] = new AMap.Marker({
                position: poi.location,   
                // 經緯度對象,也可以是經緯度構成的一維數組[116.39, 39.9]
                title: poi.name
            });
            // 將創建的點標記添加到已有的地圖實例:
            map.add(marker[i]);
            addPOIData(poi.name, poi.id, poi.location.lng, poi.location.lat);
        }
        map.setFitView();

    });
}

使用ie瀏覽器測試,在新疆附近繪製折線並查詢,刷新數據庫。
在這裏插入圖片描述

ID Name poiID Lng Lat
196 起點 undefined 87.454022 43.870275
197 途經點 undefined 87.454022 43.870275
198 途經點 undefined 87.507031 43.882154
199 途經點 undefined 87.543286 43.864334
200 途經點 undefined 87.530377 43.84017
201 途經點 undefined 87.567455 43.801329
202 途經點 undefined 87.661663 43.837001
203 終點 undefined 87.661663 43.837001
但是這樣的到的poi數據並不是理想數據。這是因爲繪製折線取點的時候不一定會取到高德地圖數據庫中擁有地名的點。可以對得到的每一個節點進行小範圍的周邊搜索,再將搜索得到的結果保存到數據庫。
document.querySelector("#search-nearby").onclick = function() {
    AMap.service(["AMap.PlaceSearch"], function() {
        // 構造地點查詢類
        var placeSearch = new AMap.PlaceSearch({
            //type: '餐飲服務', // 興趣點類別
            type: '汽車服務|汽車銷售|汽車維修|摩托車服務|餐飲服務|購物服務|生活服務|體育休閒服務|\n' +
            '\n' +
            '醫療保健服務|住宿服務|風景名勝|商務住宅|政府機構及社會團體|科教文化服務|\n' +
            '\n' +
            '交通設施服務|金融保險服務|公司企業|道路附屬設施|地名地址信息|公共設施',
            pageSize: 5, // 單頁顯示結果條數
            pageIndex: 1, // 頁碼
            city: "010", // 興趣點城市
            citylimit: true,  //是否強制限制在設置的城市內搜索
            map: map, // 展現結果的地圖實例
            panel: "panel", // 結果列表將在此容器中進行展示。
            autoFitView: true // 是否自動調整地圖視野使繪製的 Marker點都處於視口的可見範圍
        });

        //cpoint = [lng,lat]; //中心點座標,要傳入參數。
        //var cpoint = [116.433320, 39.900255]; //中心點座標,抱歉,未搜索到有效的結果
        for(j=0;j<pois.length;j++) {


            placeSearch.searchNearBy('', pois[j].location, 200, function (status, result) {
                // 查詢成功時,result即對應匹配的POI信息
                console.log(result)
                var pois0 = result.poiList.pois;
                for (var i = 0; i < pois0.length; i++) {
                    var poi = pois0[i];
                    var marker = [];
                    marker[i] = new AMap.Marker({
                        position: poi.location,   // 經緯度對象,也可以是經緯度構成的一維數組[116.39, 39.9]
                        title: poi.name
                    });
                    // 將創建的點標記添加到已有的地圖實例:
                    map.add(marker[i]);
                    addPOIData(poi.name, poi.id, poi.location.lng, poi.location.lat);
                }
                map.setFitView();

            });
        }
    });
};

在這裏插入圖片描述
以北京附近爲例,查詢之後得到的結果:
在這裏插入圖片描述

證明沿線搜索也能運行了。

總結與反思

該實驗以高德地圖JS API開發文檔爲基礎,對基礎查詢功能進行了開發。

其中沿線搜索的功能開發並不是很理想,因爲繪製的折線並沒有能很好的轉化爲包含折線帶狀區域。如果通過折線的getPath或者getBound方法得到座標進行多邊形查詢,本質都是多邊形查詢,並沒有體現“沿線”這一功能。剛開始想到將折線座標數組轉化爲多邊形座標數組(從頭到尾將折線座標偏移一遍,再反過來反方向偏移來構成一個大致包裹折線的多邊形),如下:

	var polygonArr1=[];
	var polygonArr2=[];
	var polygonB = [];
	for(i=0;i<polygonArr.length;i++){
		j=polygonArr.length-i-1;
	    polygonArr1.push([polygonArr[i][0],polygonArr[i][1]+10.000000]);
	    polygonArr2.push([polygonArr[j][0],polygonArr[j][1]-20.000000]);
	}
	var polygonB = polygonArr1.concat(polygonArr2);

但是這樣的轉化效果並不理想,適用性非常差。只能針對角度接近於180度的折線擬合。

後來想到通過規劃沿線導航進而獲取導航路徑的信息poi,經過查詢發現也不能如意。driving.search函數只能返回到傳入參數的poi信息,而不能獲取沿途的poi信息。這樣一來,沿線搜索就變成折線折點座標羣體的周邊搜索了。關於如何更好實現“沿線搜索”的問題值得深入研究。

其次,代碼邏輯性不強,有待完善。例如獲取marker(其實是獲取poi)並且存儲到數據庫的代碼,每一次不同覆蓋物查詢都用到一樣的語法邏輯。將其封裝起來成爲一個函數供調用會減少代碼重複性。每一次覆蓋物查詢(或者關鍵字查詢)都是固定不變的:

function(status, result) {
	// 查詢成功時,result即對應匹配的 POI信息
	console.log(result)
	var pois = result.poiList.pois;
	for(var i = 0; i < pois.length; i++){
	    var poi = pois[i];
	    var marker = [];
	    marker[i] = new AMap.Marker({
	        position: poi.location,   // 經緯度對象,也可以是經緯度構成的一維數組[116.39, 39.9]
	        title: poi.name
	    	});
	    // 將創建的點標記添加到已有的地圖實例:
	    map.add(marker[i]);
	    addPOIData(poi.name, poi.id, poi.location.lng, poi.location.lat);
		}
	map.setFitView();
	
	}

將這部分代碼抽取得到

// 抽取添加 marker和存儲數據的函數
function addMarkerAndPoi(status,result){
    console.log(result);
    var pois = result.poiList.pois;
    for(var i = 0; i < pois.length; i++){
        var poi = pois[i];
        var marker = [];
        marker[i]=new AMap.Marker({
            position: poi.location,
            title: poi.name
        });
        map.add(marker[i]);
        addPOIData(poi.name,poi.id,poi.location.lng,poi.location.lat);
    }
    map.setFitView();
}

將減少代碼的冗餘性,也更方便閱讀和更新。

此外,還可以針對覆蓋物開發更多的個性化功能。例如開發支持圓形的編輯;多邊形的編輯以及折線的編輯;刪除單個覆蓋物,移動覆蓋物等。高德地圖JS API示例都給出了編輯覆蓋物/矢量圖形相關教程。

通過本次開發實驗,瞭解了高德地圖JS API有關搜索查詢以及覆蓋物的簡單知識;學會如何讀懂html代碼並對相應的元素修改;學會了根據報錯信息找到代碼疏忽錯漏的地方。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章