Google Maps APIでお店のランキング表示をしてみると(2/3)
お店情報を評価順に並べて表示
「Places API」のnearbySearchで取得した情報は評価順には並んでいないので、ひと手間が必要です。
ひと手間かけたサンプルがこちら。
【サンプル2】
住所(ランドマーク名)→緯度・経度→お店情報→ratingでソート
★結果★
【サンプル2ソース】
<table>
<tr>
<td>検索場所:</td><td><input type="text" id="addressInput" value="近江町市場" style="width: 200px"></td>
</tr>
<tr>
<td>KeyWord:</td><td><input type="text" id="keywordInput" value="寿司" style="width: 200px"></td>
</tr>
<tr>
<td colspan="2" style="padding: 10px">
<input type="button" value="お店情報取得" onclick="getPlaces();">
</td>
</tr>
</table>
★結果★<br />
<div id="results" style="width: 100%; height: 200px; border: 1px dotted; padding: 10px; overflow-y: scroll; background: white;"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=xxxxxxxxxx&libraries=places"></script>
<script type="text/javascript">
var placesList;
/*
お店情報取得
*/
function getPlaces(){
//結果表示クリア
document.getElementById("results").innerHTML = "";
//placesList配列を初期化
placesList = new Array();
//入力した検索場所を取得
var addressInput = document.getElementById("addressInput").value;
if (addressInput == "") {
return;
}
//検索場所の位置情報を取得
var geocoder = new google.maps.Geocoder();
geocoder.geocode(
{
address: addressInput
},
function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
//取得した緯度・経度を使って周辺検索
startNearbySearch(results[0].geometry.location);
}
else {
alert(addressInput + ":位置情報が取得できませんでした。");
}
});
}
/*
位置情報を使って周辺検索
latLng : 位置座標(google.maps.LatLng)
*/
function startNearbySearch(latLng){
//読み込み中表示
document.getElementById("results").innerHTML = "Now Loading...";
//Mapインスタンス生成
var map = new google.maps.Map(
document.createElement("div")
);
//PlacesServiceインスタンス生成
var service = new google.maps.places.PlacesService(map);
//入力したKeywordを取得
var keywordInput = document.getElementById("keywordInput").value;
//周辺検索
service.nearbySearch(
{
location: latLng,
radius: 800,
type: ['restaurant'],
keyword: keywordInput,
language: 'ja'
},
displayResults
);
}
/*
周辺検索の結果表示
※nearbySearchのコールバック関数
results : 検索結果
status : 実行結果ステータス
pagination : ページネーション
*/
function displayResults(results, status, pagination) {
if(status == google.maps.places.PlacesServiceStatus.OK) {
//検索結果をplacesList配列に連結
placesList = placesList.concat(results);
//pagination.hasNextPage==trueの場合、
//続きの検索結果あり
if (pagination.hasNextPage) {
//pagination.nextPageで次の検索結果を表示する
//※連続実行すると取得に失敗するので、
// 1秒くらい間隔をおく
setTimeout(pagination.nextPage(), 1000);
//pagination.hasNextPage==falseになったら
//全ての情報が取得できているので、
//結果を表示する
} else {
//ソートを正しく行うため、
//ratingが設定されていないものを
//一旦「-1」に変更する。
for (var i = 0; i < placesList.length; i++) {
if(placesList[i].rating == undefined){
placesList[i].rating = -1;
}
}
//ratingの降順でソート(連想配列ソート)
placesList.sort(function(a,b){
if(a.rating > b.rating) return -1;
if(a.rating < b.rating) return 1;
return 0;
});
//placesList配列をループして、
//結果表示のHTMLタグを組み立てる
var resultHTML = "<ol>";
for (var i = 0; i < placesList.length; i++) {
place = placesList[i];
//ratingが-1のものは「---」に表示変更
var rating = place.rating;
if(rating == -1) rating = "---";
//表示内容(評価+名称)
var content = "【" + rating + "】 " + place.name;
resultHTML += "<li>";
resultHTML += content;
resultHTML += "</li>";
}
resultHTML += "</ol>";
//結果表示
document.getElementById("results").innerHTML = resultHTML;
}
} else {
//エラー表示
var results = document.getElementById("results");
if(status == google.maps.places.PlacesServiceStatus.ZERO_RESULTS) {
results.innerHTML = "検索結果が0件です。";
} else if(status == google.maps.places.PlacesServiceStatus.ERROR) {
results.innerHTML = "サーバ接続に失敗しました。";
} else if(status == google.maps.places.PlacesServiceStatus.INVALID_REQUEST) {
results.innerHTML = "リクエストが無効でした。";
} else if(status == google.maps.places.PlacesServiceStatus.OVER_QUERY_LIMIT) {
results.innerHTML = "リクエストの利用制限回数を超えました。";
} else if(status == google.maps.places.PlacesServiceStatus.REQUEST_DENIED) {
results.innerHTML = "サービスが使えない状態でした。";
} else if(status == google.maps.places.PlacesServiceStatus.UNKNOWN_ERROR) {
results.innerHTML = "原因不明のエラーが発生しました。";
}
}
}
</script>
【編集注】
Places APIの結果が英語で取得されることが多くなったため、nearbySearchにパラメータ「language:'ja'」を追加しました。
評価順にソートできてますね!
サンプル2のソースをポイント解説していきます。
[116〜154行目]
//ソートを正しく行うため、
//ratingが設定されていないものを
//一旦「-1」に変更する。
for (var i = 0; i < placesList.length; i++) {
if(placesList[i].rating == undefined){
placesList[i].rating = -1;
}
}
//ratingの降順でソート(連想配列ソート)
placesList.sort(function(a,b){
if(a.rating > b.rating) return -1;
if(a.rating < b.rating) return 1;
return 0;
});
//placesList配列をループして、
//結果表示のHTMLタグを組み立てる
var resultHTML = "<ol>";
for (var i = 0; i < placesList.length; i++) {
place = placesList[i];
//ratingが-1のものは「---」に表示変更
var rating = place.rating;
if(rating == -1) rating = "---";
//表示内容(評価+名称)
var content = "【" + rating + "】 " + place.name;
resultHTML += "<li>";
resultHTML += content;
resultHTML += "</li>";
}
resultHTML += "</ol>";
//結果表示
document.getElementById("results").innerHTML = resultHTML;
ひと手間と言っても、そんなに難しいことはしていません。
ratingの値をJavaScriptで降順にソートしてあげます。
連想配列のソートなので少し癖はありますが、書き方を真似すれば問題なしです。
ただし、ソートする前のひと手間があります。
ratingが設定されていない施設情報の場合、ratingが「undefined」となっています。
型が不一致だと上手くソートできないので、「undefined」のものは一旦「-1」に変換しておきましょう。
こうすることで、数字のみでソートができるので、正しいソート結果が得られます。
Google Maps APIを使ってお店のランキング表示をするという目標が達成できました。
せっかくなので、地図と連携して使い勝手をよくしてみましょう!