28
41

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Spring Boot + Thymeleaf + JavaScript + 駅データAPI + GoogleMapsAPIで簡単なアプリつくってみた

Last updated at Posted at 2016-12-01

概要

前回はSpringBootで郵便番号検索APIを使用して、JSON形式のレスポンスをjavaオブジェクトに変換することを紹介しました。
簡単!Spring BootでWebAPIをたたいてJSON形式のレスポンスをjavaオブジェクトに変換

今回は駅データ.jpが公開している駅データAPI、GoogleMapsAPIを使用して下記のような都道府県を選択→路線を選択→駅名を選択すると、GoogleMapに選択した駅名を表示させるアプリケーションをつくってみました!つくってみましたと言いますが、駅データ.jpにプルダウンの選択条件の絞り込みのjavascriptのサンプルがありましたので、ほぼほぼ使わせて頂き少しアレンジしただけです。あとはGoogleMapsAPI使用するためのキー取得して、controllerとtemplateつくって、都道府県のenumつくっただけです。。。

開発環境

  • macOS Sierra 10.12
  • java version 1.8.0_65
  • Spring-Boot 1.3.5
  • Thymeleaf
  • Gradle

参考資料

完成図

※mapの初期値の中心座標は東京駅に設定

都道府県選択
スクリーンショット 2016-12-01 22.40.33.png
                      |  
路線選択
スクリーンショット 2016-12-01 22.40.50.png
                      |  
駅名選択
スクリーンショット 2016-12-01 22.41.09.png
                      |  
はい!選択した駅名がmapの中心にきました!
スクリーンショット 2016-12-01 22.39.50.png
                      |  

Controller

/にアクセスして都道府県enumから都道府県コードと名称をmodelに詰めてるだけですね。
残りはJavaScriptとthymeleafだけ。

TopController.java
@Controller
public class TopController {

	@RequestMapping("/")
	public String top(HttpSession session, Model model) {
		
		PrefectureEnum[] types = PrefectureEnum.values();
		List<PrefectureDto> prefList = new ArrayList<>();
		
		for (PrefectureEnum m : types) {
			PrefectureDto dto = new PrefectureDto();
			dto.setPrefCode(m.getCode());
			dto.setPrefName(m.getFullName());
			prefList.add(dto);
		}
		model.addAttribute("prefList", prefList);
		
		return "top";
	}
}

都道府県Enum

Githubに公開しております。ご自由にお使いください!!

JavaScript

殆どこちらのサンプルのコピペですが、一番苦戦してしまいました!!何故ならJavaScriptを初めて書いたからですw
javascriptで叩いたAPIの戻り値緯度・経度をどうやってhtmlのoptionタグのバリュー値に入れて、プルダウンで選択したバリュー値をjavascriptに引き渡せばいいのかハマりました。。
formで緯度・経度をpostパラメータで渡して、次の画面でmapを表示ならすぐ出来そうでしたが、1画面でまとめたほうがスマートでユーザビリティとして間違いなく良いので、諦めませんでした!!

結局書いたjsがこちら

station.js
var xml = {};
function setMenuItem(type, code) {

	var s = document.getElementsByTagName("head")[0].appendChild(document
			.createElement("script"));
	s.type = "text/javascript";
	s.charset = "utf-8";

	var optionIndex0 = document.form.s0.options.length; // 沿線のOPTION数取得
	var optionIndex1 = document.form.s1.options.length; // 駅のOPTION数取得
	var latlng;
	var marker;

	if (type == 0) {
		for (i = 0; i <= optionIndex0; i++) {
			document.form.s0.options[0] = null
		} // 沿線削除
		for (i = 0; i <= optionIndex1; i++) {
			document.form.s1.options[0] = null
		} // 駅削除
		document.form.s1.options[0] = new Option("----", 0); // 駅OPTIONを空に
		if (code == 0) {
			document.form.s0.options[0] = new Option("----", 0); // 沿線OPTIONを空に
		} else {
			s.src = "http://www.ekidata.jp/api/p/" + code + ".json"; // 沿線JSONデータURL
		}
	} else if (type == 1) {
		for (i = 0; i <= optionIndex1; i++) {
			document.form.s1.options[0] = null
		} // 駅削除
		if (code == 0) {
			document.form.s1.options[0] = new Option("----", 0); // 駅OPTIONを空に
		} else {
			s.src = "http://www.ekidata.jp/api/l/" + code + ".json"; // 駅JSONデータURL
		}
	} else {
		var aa = document.form.s1.value;
		var data = aa.split(",");
		latlng = new google.maps.LatLng(data[0], data[1]);
		// Mapを作成
		map = new google.maps.Map(document.getElementById("map"), {
			zoom : 16,
			mapTypeId : google.maps.MapTypeId.ROADMAP, // 通常の地図
			center : latlng,
		});
		marker = new google.maps.Marker({ // マーカーの追加
			position : latlng, // マーカーを立てる位置を指定
			map : map
		// マーカーを立てる地図を指定
		});
	}

	xml.onload = function(data) {
		var line = data["line"];
		var station_l = data["station_l"];
		if (line != null) {
			document.form.s0.options[0] = new Option("----", 0); // OPTION1番目はNull
			for (i = 0; i < line.length; i++) {
				ii = i + 1 // OPTIONは2番目から表示
				var op_line_name = line[i].line_name;
				var op_line_cd = line[i].line_cd;
				document.form.s0.options[ii] = new Option(op_line_name,
						op_line_cd);
			}
		}
		if (station_l != null) {
			document.form.s1.options[0] = new Option("----", 0); // OPTION1番目はNull
			for (i = 0; i < station_l.length; i++) {
				ii = i + 1 // OPTIONは2番目から表示
				var op_station_name = station_l[i].station_name;
				var op_station_cd = station_l[i].station_cd;
				var lat = station_l[i].lat;
				var lon = station_l[i].lon;
				document.form.s1.options[ii] = new Option(op_station_name, lat
						+ "," + lon);

			}
		}
	}
}

htmlがこちら

top.html
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>都道府県から沿線/駅表示プルダウン表示</title>
<script
	src="http://maps.googleapis.com/maps/api/js?key=AIzaSyBuF7sKBPtJawa0sNDuil2ysI8vN5eXjnc"
	type="text/javascript" charset="UTF-8"></script>
<script type="text/javascript" th:src="@{/javascript/station.js}"></script>
<script type="text/javascript" th:src="@{/javascript/googlemap.js}"
	th:inline="javascript"></script>
</head>

<body onload="init()">
<div style="width: 50%;border:#d0d0d0 ridge 5px;background-color : #000080;">
	<form name="form">
		<select name="pref"
			onChange="setMenuItem(0,this[this.selectedIndex].value)">
			<option value="0" selected="selected">-----</option>
			<th:block th:each="item : ${prefList}" th:object="${item}">
				<option th:value="*{prefCode}" th:text="*{prefName}">サンプル1</option>
			</th:block>
		</select><font color="#ffffff">>></font><select name="s0"
			onChange="setMenuItem(1,this[this.selectedIndex].value)">
			<option selected="selected">----</option>
		</select><font color="#ffffff">>></font><select name="s1"
			onChange="setMenuItem(2,this[this.selectedIndex].value)">
			<option selected="selected">----</option>
		</select><br />
		<font color="#ffffff">※都道府県から路線/駅を選択してください</font>
	</form>
	</div>
	
	<div id="map" style="width: 50%; height: 400px;border:#d0d0d0 ridge 5px;"></div>
</body>
</html>

サンプルに少しアレンジを加えました。何をしたかというと路線を選択したときに、駅名のオプションタグにnameに駅名、value値に緯度と経度を,(カンマ)区切りで結合させセットさせるようにしました。
そして、駅名のプルダウンで選択されたバリュー値を下記のようにjavascriptで取得し、,(カンマ)でスプリットさせ緯度、経度を取得することに成功しました!!!もっとスマートに書けそうな気がするんだけどな〜〜何かご指摘あればお願いします!
あとはGoogleMapを作成し、緯度経度をセットし、ついでにマーカーもセットしておきました。

var aa = document.form.s1.value;
        var data = aa.split(",");
        latlng = new google.maps.LatLng(data[0], data[1]);
        // Mapを作成
        map = new google.maps.Map(document.getElementById("map"), {
            zoom : 16,
            mapTypeId : google.maps.MapTypeId.ROADMAP, // 通常の地図
            center : latlng,
        });
        marker = new google.maps.Marker({ // マーカーの追加
            position : latlng, // マーカーを立てる位置を指定
            map : map
        });

初期値のGoogleMapを表示するjsはこれだけ

googlemap.js
var map;
var latlng;

function init() {
	// map初期作成 東京駅の緯度経度を設定
	latlng = new google.maps.LatLng(35.681298, 139.766247);
	// Mapを作成
	map = new google.maps.Map(document.getElementById("map"), {
		zoom : 16,
		mapTypeId : google.maps.MapTypeId.ROADMAP, // 通常の地図
		center : latlng,
	});
}

GoogleMapsAPIキーの取得はこちらをご参照ください。すぐに取得できます。
GoogleDeveloperConsolesのこんな画面で受け入れるURLを設定するだけですね。

スクリーンショット 2016-12-01 23.40.52.png

まとめ

この記事を見て自分でも何か作ってみようと思うきっかけになり、何かお役に立つ事が出来ましたら幸いです。最後まで読んで頂き、ありがとうございました。
何かご指摘等ございましたらコメントに記載してくださるとありがたいです。

使用したコード

Githubにソースコード公開しております。
https://github.com/keiyonekawa0614/awakenoy0614/tree/master/Sample

P.S.

下記記事を参考に私のSpringBoot起動時はこんな感じですw
Spring Bootの起動バナーの変更

SpringBoot起動するゾー!
スクリーンショット 2016-12-02 0.40.29.png
                      |  
28
41
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
41

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?