จากตอนที่แล้ว ได้ทำการแจก ionic material ตัวปรับแต่ง เพื่อ
เป็นแนวทางต่อยอดในการศึกษาเพิ่มเติม การสร้าง android app ด้วย
ionicframework
โหลดฟรี ionic material ตัวปรับแต่ง สำหรับประยุกต์เพิ่มเติม
https://www.ninenik.com/content.php?arti_id=729 via @ninenik
ในตอนนี้เราจะมาทำการแสดง google map ใน app ของเรา
แต่ก่อนอื่นเรามาเช็คก่อนว่า phonegap ได้เพิ่ม plugin ให้เราตั้งแต่แรก
มีอะไรบ้าง (ปกติจะมีมาครบ) โดยใช้คำสั่ง
C:\phonegap\learn001>phonegap plugin ls
นี่คือรายการ plugin เริ่มเต้นที่ phonegap ติดตั้งให้เราแล้ว
cordova-plugin-battery-status 1.1.2 "Battery" cordova-plugin-camera 2.1.1 "Camera" cordova-plugin-compat 1.0.0 "Compat" cordova-plugin-console 1.0.4 "Console" cordova-plugin-contacts 2.0.1 "Contacts" cordova-plugin-device 1.1.3 "Device" cordova-plugin-device-motion 1.2.2 "Device Motion" cordova-plugin-device-orientation 1.0.4 "Device Orientation" cordova-plugin-dialogs 1.2.1 "Notification" cordova-plugin-file 4.3.0 "File" cordova-plugin-file-transfer 1.5.1 "File Transfer" cordova-plugin-geolocation 2.1.0 "Geolocation" cordova-plugin-globalization 1.0.4 "Globalization" cordova-plugin-inappbrowser 1.3.0 "InAppBrowser" cordova-plugin-media 2.2.0 "Media" cordova-plugin-media-capture 1.2.0 "Capture" cordova-plugin-network-information 1.2.1 "Network Information" cordova-plugin-splashscreen 3.2.2 "Splashscreen" cordova-plugin-statusbar 2.1.3 "StatusBar" cordova-plugin-vibration 2.1.2 "Vibration" cordova-plugin-whitelist 1.2.2 "Whitelist"
ถึงตรงนี้ใช่ว่า app ของเราจะต้องใช้ plugin นี้ทั้งหมดในตอนนี้
แต่เพื่อไม่ให้เสียเวลา เราจะข้ามตรงนี้ไป คือให้ใช้ plugin เริ่มต้นทั้งหมดใน app
การแสดงแผนที่ google map ใน app ของเราจะเป็นรูปแบบอย่างง่ายก่อน คือ
จะทำการเพิ่มเมนูคำว่า map ใน side menu ด้านซ้าย
สร้าง router หรือเส้นทางของ url หน้า app ใหม่
สร้าง ไฟล์แสดง หน้า app ใหม่
สร้าง controller และฟังก์ชันแสดง google map
กำหนดรูปแบบ css เพิ่มเติมถ้าจำเป็น
1. สร้าง router หรือเส้นทางของ url หน้า app ใหม่
ให้เปิดไฟล์ app.js ในโฟลเดอร์ js แทรกโค้ดดังนี้เข้าไป
.state('app.map', {// กำหนด state url: '/map', // กำหนดตำแหน่งหน้า app คล้ายๆ url ในเว็บ views: { 'menuContent': { // ส่วนของการแสดงใน view ชื่อ menuContent templateUrl: 'templates/map.html', // ใช้ template ชื่อ map.html controller: 'MapCtrl'// กำหนดชื่อ controller ที่จะใช้งาน }, 'fabContent': { // ส่วนของการแสดงใน view ชื่อ fabContent ไม่ได้กำหนดอะไร template: '' } } }) // ศึกษา state และ template ที่เนื้อหานี้ // ionic material ภาคต่อ การทำงานของ state และ template ตอนที่ 2 // https://www.ninenik.com/content.php?arti_id=698 via @ninenik
จะได้ app.js เป็นดังนี้
angular.module('starter', [ 'ionic', 'ngCordova','starter.services','starter.controllers', 'ionic-material', 'ionMdInput'] ) .run(function($ionicPlatform,$ionicPopup,$cordovaDialogs) { $ionicPlatform.ready(function() { if (window.cordova && window.cordova.plugins.Keyboard) { cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true); } if (window.StatusBar) { StatusBar.styleDefault(); } }); }) .config(function($stateProvider, $urlRouterProvider, $ionicConfigProvider) { $ionicConfigProvider.views.maxCache(0); $stateProvider.state('app', { url: '/app', abstract: true, templateUrl: 'templates/menu.html', controller: 'AppCtrl' }) .state('app.login', { url: '/login', views: { 'menuContent': { templateUrl: 'templates/login.html', controller: 'LoginCtrl' }, 'fabContent': { template: '' } } }) .state('app.register', { url: '/register', views: { 'menuContent': { templateUrl: 'templates/register.html', controller: 'RegistCtrl' }, 'fabContent': { template: '' } } }) .state('app.profile', { url: '/profile', views: { 'menuContent': { templateUrl: 'templates/profile.html', controller: 'ProfileCtrl' }, 'fabContent': { template: '<button id="fab-profile" class="button button-fab button-fab-bottom-right button-energized-900"><i class="icon ion-plus"></i></button>', controller: function ($timeout) { } } } }) .state('app.map', {// กำหนด state url: '/map', // กำหนดตำแหน่งหน้า app คล้ายๆ url ในเว็บ views: { 'menuContent': { // ส่วนของการแสดงใน view ชื่อ menuContent templateUrl: 'templates/map.html', // ใช้ template ชื่อ map.html controller: 'MapCtrl'// กำหนดชื่อ controller ที่จะใช้งาน }, 'fabContent': { // ส่วนของการแสดงใน view ชื่อ fabContent ไม่ได้กำหนดอะไร template: '' } } }) // ศึกษา state และ template ที่เนื้อหานี้ // ionic material ภาคต่อ การทำงานของ state และ template ตอนที่ 2 // https://www.ninenik.com/content.php?arti_id=698 via @ninenik $urlRouterProvider.otherwise('/app/login'); });
2. สร้างไฟล์ template หน้า app ที่เราต้องการแสดงแผนที่
ชื่อ map.html ไว้ในโฟลเดอร์ templates ดังนี้
<ion-view view-title="Map" ng-init="init()"> <ion-nav-buttons side="right"> <div class="buttons buttons-right header-item"> <span class="right-buttons"> <button class="button button-icon button-clear ion-android-more-vertical"> </button> </span> </div> </ion-nav-buttons> <ion-content ng-class="{expanded:isExpanded}"> <div id="map" data-tab-disabled="true"></div> </ion-content> </ion-view>
สังเกตจะเห็นว่า เรามีการกำหนดให้มีการเรียกใช้งานฟังก์ชั่นเริ่มต้นทันที
ที่เข้ามาหน้าแผนที่ ด้วย ng-init="init()" นั่นก็คือเมื่อหน้า view ของ map
แสดง ฟังก์ชั่นที่ชื่อ init() จะถูกเรียกทำงาน
นอกจากนั้นในหน้าแสดงแผนที่ เราได้มีการกำหนด
<div id="map" data-tab-disabled="true"></div>
เพื่อเป็นส่วนที่ใช้แสดงแผนที่ การกำหนด data-tap-disabled ก็เพื่อป้องการ
การทำงานของ ng-click เพื่อให้เราสามารถคลิกส่วนต่างๆ ใน google map ได้
3. กำหนด css style ให้กับแผนที่ และการแสดงแผนที่ให้แสดงเต็มส่วนของเนื้อหา
ให้เปิดไฟล์ style.css ในโฟลเดอร์ css
แล้วแทรกโค้ด css นี้เข้าไป ด้านล่างสุด
/* Map ==================================*/ .scroll{ height:100%; } #map{ width:100%; height:100%; }
4. สร้าง controller เพื่อควบคุมการทำงานของหน้าแผนที่
ให้เปิดไฟล์ชื่อ controllers.js ในโฟลเดอร์ js ให้แทรกโค้ดนี้เข้าไปก่อน ProfileCtrl
.controller('MapCtrl', function( $scope, $stateParams, $timeout, ionicMaterialInk, ionicMaterialMotion ,$ionicPlatform ) { $scope.$parent.showHeader(); $scope.$parent.clearFabs(); $scope.$parent.setHeaderFab(false); $scope.$parent.hasShadow(); $timeout(function() { $scope.isExpanded = false; $scope.$parent.setExpanded(false); }, 300); // สร้างฟังก์ชั่นแสดงแผนที่ $scope.init = function(){ // กำหนดตำแหน่งของแผนที่ var myLatLng = new google.maps.LatLng(13.766396943088147,100.63905715942383); // กำนหนด option การแสดงแผนที่ var mapOption = { center:myLatLng, zoom:13, mapTypeId:google.maps.MapTypeId.ROADMAP }; // แสดงแผนที่ในตำแหน่ง div id=map var map = new google.maps.Map(document.getElementById("map"),mapOption); // กำหนดค่าตัวแปร map เผื่อได้เรียกใช้งาน $scope.map = map; }; ionicMaterialMotion.fadeSlideInRight(); ionicMaterialInk.displayEffect(); })
จะได้ไฟล์ controllers.js เป็นดังนี้
'use strict'; angular.module('starter.controllers', []) .controller('AppCtrl', function($scope, $ionicModal, $ionicPopover, $timeout, $ionicPopup) { $scope.loginData = {}; $scope.isExpanded = false; $scope.hasHeaderFabLeft = false; $scope.hasHeaderFabRight = false; var navIcons = document.getElementsByClassName('ion-navicon'); for (var i = 0; i < navIcons.length; i++) { navIcons.addEventListener('click', function() { this.classList.toggle('active'); }); } //////////////////////////////////////// // Layout Methods //////////////////////////////////////// $scope.hideNavBar = function() { document.getElementsByTagName('ion-nav-bar')[0].style.display = 'none'; }; $scope.showNavBar = function() { document.getElementsByTagName('ion-nav-bar')[0].style.display = 'block'; }; $scope.noHeader = function() { var content = document.getElementsByTagName('ion-content'); for (var i = 0; i < content.length; i++) { if (content[i].classList.contains('has-header')) { content[i].classList.toggle('has-header'); } } }; $scope.setExpanded = function(bool) { $scope.isExpanded = bool; }; $scope.setHeaderFab = function(location) { var hasHeaderFabLeft = false; var hasHeaderFabRight = false; switch (location) { case 'left': hasHeaderFabLeft = true; break; case 'right': hasHeaderFabRight = true; break; } $scope.hasHeaderFabLeft = hasHeaderFabLeft; $scope.hasHeaderFabRight = hasHeaderFabRight; }; $scope.hasHeader = function() { var content = document.getElementsByTagName('ion-content'); for (var i = 0; i < content.length; i++) { if (!content[i].classList.contains('has-header')) { content[i].classList.toggle('has-header'); } } }; $scope.hideHeader = function() { $scope.hideNavBar(); $scope.noHeader(); }; $scope.showHeader = function() { $scope.showNavBar(); $scope.hasHeader(); }; $scope.clearFabs = function() { var fabs = document.getElementsByClassName('button-fab'); if (fabs.length && fabs.length > 1) { fabs[0].remove(); } }; $scope.noShadow = function() { var headerBar = document.getElementsByTagName('ion-header-bar'); for (var i = 0; i < headerBar.length; i++) { if (!headerBar[i].classList.contains('no-shadow')) { headerBar[i].classList.add('no-shadow'); } } }; $scope.hasShadow = function() { var headerBar = document.getElementsByTagName('ion-header-bar'); for (var i = 0; i < headerBar.length; i++) { if (headerBar[i].classList.contains('no-shadow')) { headerBar[i].classList.remove('no-shadow'); } } }; }) .controller('LoginCtrl', function($scope, $timeout, $stateParams, ionicMaterialInk) { $scope.$parent.clearFabs(); $scope.$parent.hasShadow(); $timeout(function() { $scope.$parent.hideHeader(); }, 0); ionicMaterialInk.displayEffect(); }) .controller('RegistCtrl', function($scope, $timeout, $stateParams, ionicMaterialInk) { $scope.$parent.clearFabs(); $scope.$parent.hasShadow(); $timeout(function() { $scope.$parent.hideHeader(); }, 0); ionicMaterialInk.displayEffect(); }) .controller('MapCtrl', function( $scope, $stateParams, $timeout, ionicMaterialInk, ionicMaterialMotion ,$ionicPlatform ) { $scope.$parent.showHeader(); $scope.$parent.clearFabs(); $scope.$parent.setHeaderFab(false); $scope.$parent.hasShadow(); $timeout(function() { $scope.isExpanded = false; $scope.$parent.setExpanded(false); }, 300); // สร้างฟังก์ชั่นแสดงแผนที่ $scope.init = function(){ // กำหนดตำแหน่งของแผนที่ var myLatLng = new google.maps.LatLng(13.766396943088147,100.63905715942383); // กำนหนด option การแสดงแผนที่ var mapOption = { center:myLatLng, zoom:13, mapTypeId:google.maps.MapTypeId.ROADMAP }; // แสดงแผนที่ในตำแหน่ง div id=map var map = new google.maps.Map(document.getElementById("map"),mapOption); // กำหนดค่าตัวแปร map เผื่อได้เรียกใช้งาน $scope.map = map; }; ionicMaterialMotion.fadeSlideInRight(); ionicMaterialInk.displayEffect(); }) .controller('ProfileCtrl', function($scope, $stateParams, $timeout, ionicMaterialMotion, ionicMaterialInk) { $scope.$parent.showHeader(); $scope.$parent.clearFabs(); $scope.isExpanded = false; $scope.$parent.setExpanded(false); $scope.$parent.setHeaderFab(false); $scope.$parent.hasShadow(); $timeout(function() { ionicMaterialMotion.slideUp({ selector: '.slide-up' }); }, 300); $timeout(function() { ionicMaterialMotion.fadeSlideInRight({ startVelocity: 3000 }); }, 700); ionicMaterialInk.displayEffect(); }) ;
5. สร้างเมนูใน side menu เพื่อให้คลิกไปยังหน้าแผนที่ ได้
เปิดไฟล์ menu.html ในโฟลเดอร์ templates แล้วเพิ่ม เมนู Map
เข้าไปดังนี้
<ion-side-menus enable-menu-with-back-views="true"> <ion-side-menu-content> <ion-nav-bar class="bar-dark" ng-class="{expanded: isExpanded, 'has-header-fab-left': hasHeaderFabLeft, 'has-header-fab-right': hasHeaderFabRight}" align-title="left"> <!--<ion-nav-back-button class="no-text">--> <!--</ion-nav-back-button>--> <ion-nav-buttons side="left"> <button class="button button-icon button-clear ion-navicon" menu-toggle="left"> </button> </ion-nav-buttons> </ion-nav-bar> <ion-nav-view name="fabContent"></ion-nav-view> <ion-nav-view name="menuContent" ng-class="{expanded: isExpanded}" ></ion-nav-view> </ion-side-menu-content> <ion-side-menu side="left"> <ion-header-bar class="bar expanded dark-bg"> <span class="avatar" style="background: url('img/crown.jpg'); background-size: cover;"></span> <h2>Demo App</h2> </ion-header-bar> <ion-content class="stable-bg has-expanded-header"> <ion-list> <ion-item nav-clear menu-close ui-sref="app.login"> Login </ion-item> <ion-item nav-clear menu-close ui-sref="app.register"> Register </ion-item> <ion-item nav-clear menu-close ui-sref="app.profile"> Profile </ion-item> <ion-item nav-clear menu-close ui-sref="app.map"> Map </ion-item> <ion-item nav-clear menu-close ui-sref="app.login"> Logout </ion-item> </ion-list> </ion-content> </ion-side-menu> </ion-side-menus>
สังเกตว่าเมนู Map จะมีการเรียกไปที่ state app.map ซึ่งก็คือหน้าแสดง
แผนที่ google map ที่เราสร้างข้าง
6. ส่วนสุดท้าย ก็คือการเรียก google map library มาใช้
โดยแทรก script ในไฟล์ index.html
<script src="https://maps.googleapis.com/maps/api/js?key=your_key" async defer></script>
your_key สามารถขอรับได้ที่ https://developers.google.com/maps/web/
จะได้ไฟล์ index.html เป็นดังนี้
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"> <title></title> <link href='https://fonts.googleapis.com/css?family=RobotoDraft:400,500,700,400italic' rel='stylesheet' type='text/css'> <link href="lib/ionic/css/ionic.css" rel="stylesheet"> <link href="lib/ion-md-input/css/ion-md-input.min.css" rel="stylesheet"> <link href="lib/ionic-material/dist/ionic.material.min.css" rel="stylesheet"> <link href="css/style.css" rel="stylesheet"> <script src="https://maps.googleapis.com/maps/api/js?key=your_key" async defer></script> <script src="lib/ionic/js/ionic.bundle.js"></script> <script src="lib/ionic-material/dist/ionic.material.min.js"></script> <script src="lib/ion-md-input/js/ion-md-input.min.js"></script> <!-- cordova script (this will be a 404 during development) --> <script src="lib/ng-cordova/ng-cordova.js"></script> <script src="cordova.js"></script> <!-- your app's js --> <script src="js/app.js"></script> <script src="js/services.js"></script> <script src="js/controllers.js"></script> </head> <body ng-app="starter"> <ion-nav-view></ion-nav-view> </body> </html>
7. ทำการ build apk ไฟล์แล้วนำไปทดสอบติดตั้งบนมือถือ
ด้วยคำสั่ง
C:\phonegap\learn001>phonegap build android
ให้ทำการทดสอบติดตั้งในมือถือ android ของเรา จะได้หน้าตา app ประมาณนี้
จะเห็นว่ามีเมนู Map เพิ่มเข้ามา และเมื่อเรากดเข้าไป ก็จะไปที่หน้าแผนที่
และแสดงแผนที่ตามที่เรากำหนด