2015年5月9日 星期六

Hybrid Apps開發系列之6.2:使用Google Maps API顯示地圖

地圖服務是行動apps最常提供的功能。本文介紹如何在Ionic Apps裡使用Google Maps API顯示地圖。
 圖1. 顯示Google Map

前置動作:產生Google API Key

Google API的使用方式如下:
http://maps.googleapis.com/maps/api/js?key=[你的API金鑰]&sensor=true
因此必須先取得API金鑰,步驟如下:
  1. 前往Google Developers Console (https://console.developers.google.com/)。
  2. 以gmail帳號登入後,點選「建立專案」,並輸入專案名稱。
  3. 進到專案頁面,選取左側選單「API和驗證」項目下的「API」,從右邊各種API列表中選取Google Maps JavaScript API,並在下一個畫面啟動之。
  4. 在「API和驗證」項目下的「憑證」頁面,點選「建立新的金鑰」,選擇「瀏覽器金鑰」,並輸入http:/localhost:8100/*。
  5. 將「API 金鑰」複製起來,放到index.html引用Google Maps API的地方,例如:
  6. <script src="http://maps.googleapis.com/maps/api/js?key=[你的API 金鑰]&sensor=true"></script>

此外,如果需要行動平台的目前位置資訊,則需要安裝Apache Cordova Geolocation外掛。
cordova plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-geolocation.git

建立Ionic 專案

ionic start GoogleMap blank
cd GoogleMap
ionic platform add android
cordova plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-geolocation.git

加入Google Maps API

Google Maps API無法下載放進專案內,必須直接加入index.html:
<!-- your app's js -->
<script src="js/app.js"></script>
<script src="js/services.js"></script>
<script src="http://maps.googleapis.com/maps/api/js?key=[API金鑰]&sensor=true"></script>
將前置動作取得的API key置換上去,便完成設定。

程式碼說明

如圖1所示,範例程式有兩個頁面:清單頁面templates/list.html與細節瀏覽頁面templates/detail.html,Google地圖置於後頁。資料部份與地圖呼叫服務放在js/services.js(請在index.html內加入js/services.js的設定,並於js/app.js注入js/services.js內的自訂模組),方便後續擴充。

js/services.js

  1. angular.module('starter.services', [])
  2. .factory('MAP', function () {
  3. var self = this;
  4. self.initialize = function (id) {
  5. var LatLng = navigator.geolocation.getCurrentPosition(function (pos) {
  6. return new google.maps.LatLng(pos.coords.latitude,
  7. pos.coords.longitude)
  8. }) // 目前位置
  9. var mapOptions = {
  10. center: LatLng,
  11. zoom: 15,
  12. mapTypeId: google.maps.MapTypeId.ROADMAP
  13. };
  14. var map = new google.maps.Map(document.getElementById(id), mapOptions);
  15. return map;
  16. }
  17.  
  18. self.setLocation = function (map, pos) {
  19. var marker = new google.maps.Marker({
  20. position: new google.maps.LatLng(pos.lat, pos.lng),
  21. map: map,
  22. title: pos.title
  23. });
  24. map.setCenter(marker.getPosition());
  25. return map;
  26. }
  27. return self
  28. })
  29. .value('POIs', [{
  30. "entrance": "宜蘭縣南澳鄉",
  31. "level": "國家級步道",
  32. "manager": "羅東林區管理處",
  33. "name": "蘇花古道:大南澳越嶺段",
  34. "number": "1",
  35. "second_system": "無",
  36. "system": "蘇花-比亞毫國家步道系統",
  37. "latlng": [24.26467, 121.740875]
  38. }, {
  39. ...[略]...
  40. }]);
  • 第4-16行:定義initialize()。其中第5行使用Cordova Geolocation外掛,取得現在位置的經緯度,做為地圖的預設位置。其餘都是根據Google Maps API的文件說明,建立地圖。詳情可參考Google Maps API官網
  • 第18-26行:定義setLocation()。同樣根據Google Maps API的文件說明,建立marker,並以marker為中心顯示地圖。
  • 第29行以後:步道資料部份。

主程式js/app.js

  1. var map=null;
  2. angular.module('starter', ['ionic', 'starter.services'])
  3. .config(function ($stateProvider, $urlRouterProvider) {
  4. $stateProvider
  5. .state('list', {
  6. url: '/list',
  7. templateUrl: 'templates/list.html',
  8. controller: 'listCtrl'
  9. })
  10. .state('detail', {
  11. url: '/list/:id',
  12. templateUrl: 'templates/detail.html',
  13. controller: 'detailCtrl'
  14. })
  15. $urlRouterProvider.otherwise('/list')
  16. })
  17. .controller('listCtrl', function ($scope, POIs, $location) {
  18. $scope.pois = POIs;
  19. $scope.detail = function (id) {
  20. $location.path('/list/' + id);
  21. }
  22. })
  23. .controller('detailCtrl', function ($scope, MAP, $stateParams, POIs, $filter) {
  24. $scope.poi = $filter('filter')(POIs, {number: $stateParams.id})[0];
  25. map = MAP.initialize('map'); // 載入地圖 'map'是顯示地圖區塊的id
  26. var marker = {lat: ($scope.poi.latlng)[0], lng: ($scope.poi.latlng)[1], title: $scope.poi.name};
  27. MAP.setLocation(map, marker);
  28.  
  29. })
  • 第2行:注入starter.services模組。定義於js/services.js內。注意index.html也必須加入:
    <script src="js/services.js"></script>
  • 第4-16行:定義兩個states。第11行url值設定為'/list/:id',id便成為之後頁面傳遞的參數名稱。
  • 第17-22行:清單頁面的controller。其中POIs是js/services.js以.value()定義的步道資料內容。第19行的id對應到步道資料內容的'number'欄位。
  • 第23-29行:細節瀏覽頁面的controller。MAP是js/services.js以.factory()定義的Google Maps相關服務。
  • 第24行:以$filter('filter')(array, 過濾條件)的方式,從POIs篩出要顯示的資料。此處用number欄位,篩出值為$stateParams.id的資料。
  • 第25行:建立Google地圖。Map.initialize()的參數是顯示地圖<div>的id設定值。
  • 第26行:建立marker。
  • 第27行:以marker為中心顯示地圖。

templates/list.html, templates/detail.html與css/style.css

list.html檔
  1. <ion-view title="步道系統">
  2. <ion-content>
  3. <ion-list ng-repeat="item in pois">
  4. <ion-item ng-click="detail({{item.number}})">
  5. {{item.name}}
  6. </ion-item>
  7. </ion-list>
  8. </ion-content>
  9. </ion-view>
detail.html檔
  1. <ion-view title="{{poi.name}}">
  2. <ion-content>
  3. <div class="card list">
  4. <div class="item item-avatar-left">
  5. <img src="img/ionic.png">
  6. <h2>{{poi.name}}</h2>
  7. <p class="row">
  8. <span class="col-20">地點</span><span class="col-80">{{poi.entrance}}</span>
  9. </p>
  10. <p class="row">
  11. <span class="col-20">等級</span><span class="col-80">{{poi.level}}</span>
  12. </p>
  13. <p class="row">
  14. <span class="col-20">系統</span><span class="col-80">{{poi.system}}</span>
  15. </p>
  16. </div>
  17. <div class="item item-body">
  18. <div class="row">
  19. <div class="col col-center">
  20. <div style="width:250px;height:250px;" id="map" data-tap-disabled="true"></div>
  21. </div>
  22. </div>
  23. </div>
  24. </div>
  25. </ion-content>
  26. </ion-view>
自訂CSS:css/style.css,由於ionic的加了許多css設定,此檔覆蓋一些css設定,讓google地圖能正常顯示。
  1. .scroll {
  2. height: 100%;
  3. }
  4. #map {
  5. width: 100%;
  6. height: 100%;
  7. }
完整程式可參考GitHub Gist專案

沒有留言:

張貼留言