2014年9月23日 星期二

Angularjs Route Using Google Map API JSON

.

一、當單一頁面中有許多連結時通常會透過連結來換頁,但若我們希望停留在原頁面並使用到共用功能時可以透過場景的轉變來達成,而透過Angularjs中的ng-view、$routeProvider便可進行切換,另外要注意的是因為都在同一頁切換,所以在URL參數上會在#之後e.g(/index.html#/list)。


二、此範例中結合Google Map API JSON來輸入地址抓取地址名稱、經緯度,但可能一個地址有著其他相同的地方,故以List方式列出,點擊之後便切換場景到detail.html用來顯示地圖並綁定資料來達成下一張與上一張的功能。

    (一)首先我們可以參考google map api的說明,並了解到使用方式(http://maps.googleapis.com/maps/api/geocode/json?address=您想要的地址&sensor=false&language=zh-TW),而取回來的JSON格式我們只需要從results陣列內取每個元素中的formatted_address、geometry.location.lat、geometry.location.lng因此必須撰寫JSON Parser來剖析。
    (二)取得地址、經、緯度之後可以到google static maps 了解使用方式如:http://maps.google.com/maps/api/staticmap?center=台北市&zoom=10&size=800x500&sensor=false&markers=color:blue%7Clabel:S%7C110台灣台北市信義區台北101,便可順利取得靜態地圖圖片。
    (三)切換場景可以使用
$routeProvider.when('/list',{
            templateUrl: 'listView.html',
            controller: 'listDetailController'
        }).when('/details/:detailsID',{
            templateUrl: 'detail.html',
            controller: 'listDetailController'
        }).otherwise({
            redirectTo: '/list'
        })
    (四)而上一筆、下一筆的實作方式,可用whichID搭配$routeParams.detailsID來記錄目前頁、prevGuitar前一頁、nextGuitar下一頁並綁定數據於detail.html。

三、設計index.html,而textbox及button為頁面共用控件,故使用ng-view來表示要切換場景的區塊,其中<input ..>以inputAddress做為ng-model來綁定輸入時的地址。

<html ng-app='appModule'>
<head>
    <meta charset="UTF-8">
    <link href="../../css/kendo.common.min.css" rel="stylesheet" />
    <link href="../../css/kendo.default.min.css" rel="stylesheet" />
    <link href="../../css/bootstrap.min.css" rel="stylesheet" />
    <link href="../css/kendo-ui-li.css" rel="stylesheet" />
    <link href="../css/listView.css" rel="stylesheet" />


    <script src="../../js/bootstrap.min.js"></script>
    <script src="../../js/jquery.min.js"></script>
    <script src="../../js/angular.min.js"></script>
    <script src="../../js/angular-route.min.js"></script>
    <script src="../../js/kendo.all.min.js"></script>
    <script src="../../js/bootstrap.min.js"></script>

    <script src="../controller/app.js"></script>
    <script src="../controller/jsonParser.js"></script>
    <script src="../controller/controller.js"></script>
    <title></title>
</head>
<body ng-controller='appController'>
<div class="bg-success center" ng-init="setAddressLists(inputAddress)">
    <input  kendo-auto-complete
            type="text"
            ng-model="inputAddress"
            placeholder="Please Input Address..."
            ng-keyup="inputKeyup($event,inputAddress)"/>
    <button class="btn btn-warning margin"
            ng-click="setAddressLists(inputAddress)" >
        Search
    </button>

<div ng-controller="listDetailController" align="center" ng-view></div>

</div>


</body>
</html>

四、由於json需要剖析故設計jsonParser.js的Factory,來運行json的抓取與剖析,其中getAddressDatas主要將取得的jsonCollection進行尋訪並從中取出formatted_address、lat、lng後回傳。

var jsonParserConstructor = function(){
    var DataClass = function (formatted_address,lat,lng) {
        this.formatted_address = formatted_address;
        this.lat = lat;
        this.lng = lng;
    };
    var firstParagraph = "http://maps.googleapis.com/maps/api/geocode/json?address=";
    var lastParagraph = "&sensor=false&language=zh-TW";
    var jsonParserApp = angular.module('jsonParserModule',[]);
    jsonParserApp.factory('jsonParserFactory',function($q,$http){
        return{
            getAddressJson: function(inputAddress){
                var url = firstParagraph.concat(inputAddress,lastParagraph);
                var deferred = $q.defer();
                $http.get(url).success(function(data,status, headers, config){
                    deferred.resolve(data);
                }).error(function (data, status, headers, config){
                    deferred.reject(data);
                });
                return deferred.promise;
            },
            getAddressDatas: function(collectionJson){
                    var datas = new Array();
                    angular.forEach(collectionJson.results,function(result){
                        var data = new DataClass(result.formatted_address,result.geometry.location.lat,result.geometry.location.lng);
                        datas.push(data);
                    });
                    return datas;
            }
        }
    });
}();

五、設計controller.js,共有appController、listDetailController,而appController進行一些資料設定,listDetailController則紀錄whichId、prevGuitar、nextGuitar來進行上下筆切換。

var controllerConstructor = function(){
    var app = angular.module('controllerModule',['ngRoute']);
    app.controller('appController',function(jsonParserFactory,$scope,$location){
        $scope.datas = [];
        $scope.inputAddress = "大寮";
        $scope.enterKeyCode = 13;
        $scope.inputKeyup = function(e,inputAddress){
            if (e.keyCode == $scope.enterKeyCode && inputAddress)
                $scope.setAddressLists(inputAddress);
        }
        $scope.setAddressLists = function(inputAddress){
            $location.url('/list');
            jsonParserFactory.getAddressJson(inputAddress).then(function(collectionJson){
                $scope.datas = jsonParserFactory.getAddressDatas(collectionJson);
            });
            $scope.inputAddress = '';
        };
        $scope.placeholder = function(element) {
            return element.clone().addClass("placeholder").text("drop here");
        };
        $scope.hint = function(element) {
            return element.clone().addClass("hint");
        };

    });
    app.controller('listDetailController',function($scope,$routeParams){
        $scope.whichId = parseInt($routeParams.detailsID);
        if($routeParams.detailsID > 0)
            $scope.prevGuitar = $scope.whichId-1;//前一筆
        else
            $scope.prevGuitar = $scope.datas.length-1;//小於0則設為最後一筆
        $scope.nextGuitar = ($scope.whichId + 1) % $scope.datas.length;
    });
}();

六、撰寫listView.html利用ng-repeat印出formatted_address及設定連結。

<div>
<ol class="playlist" kendo-sortable k-placeholder="placeholder" k-hint="hint">
    <li ng-repeat="data in datas">
        <a id="detail" href="#/details/{{datas.indexOf(data)}}" >
        {{data.formatted_address}}
        </a>
    </li>
</ol>
</div>

七、最後則設計detail.html,並利用whichId綁定數據,prevGuitar與nextGuitar則搭配連結用來切換上下筆。

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<h3><span class="label label-default">{{datas[whichId].formatted_address}}</span></h3>

<br />
<img class="img-thumbnail" ng-src="http://maps.google.com/maps/api/staticmap?center={{datas[whichId].formatted_address}}&zoom={{zoom}}&size=800x500&sensor=false&markers=color:blue%7Clabel:S%7C{{datas[whichId].formatted_address}}"/>
<hr/>
<div class="navigation">
    <a class="btn btn-info" href="#/details/{{prevGuitar}}">&lt;</a>
    <a class="btn btn-info" href="#/details/{{nextGuitar}}">&gt;</a>
</div>
</body>
</html>

沒有留言:

張貼留言