Posted at

○○mapを作るアプリを作ってみた!

More than 3 years have passed since last update.

この記事は、シビックテックをテーマにした、「Civic Tech Advent Calendar 2015」企画の12日目の原稿です。他の記事は

http://qiita.com/advent-calendar/2015/civictech


この記事を書いた理由

私はニフティクラウド mobile backendの中の人ですが、今年ハッカソンを通して、多くのCivic Techの作品に使っていただいたので、今年の最後に恩返しのアウトプットとして書きました。

今回はよくcivic techで見かける「○○map」(保育園map、消火栓map)を簡単に作れるアプリを作ってみたのを記事にします!


使うサービス

ニフティクラウド mobile backend

mobile backend as a Service 略して mBaaS

スマホアプリのサーバー側の機能、プッシュ通知、データベースなどの機能をAPI,SDKを作り込み簡単に導入できるようになっているサービス。位置情報検索といった、データベース上にGPS情報などを保存し、現在地から近いポイントを絞り込んで検索できる機能もある。(今回はJSSDKでこの機能を使う)

Monaca

HTML5,JSでハイブリットアプリが作れるツール。JSでコードをカメラや加速度センサ、GPSなどのセンサ情報にもアクセスできるという強力なツール、デバッガーもあり、ビルドなしで実際のアプリの挙動もみれるのが強力。

OpenStreetMap

オープンに使えるマップ、マーカーなんかも描画できる。


作ったアプリの使用

※以下は全部monacaデバッガーでのスクショ

まずホーム画面で、現在地を中心として地図を表示できます。上野駅でアプリを立ち上げたとすると下のように表示される。

home.png

ポイントを保存するボタンを押すと以下のようになる

input.png

ポイントを見るボタンを押すと以下のように周囲(5km以内)の登録されたポイントを見れる

hyouji.png


各サービスの登録設定及びコードは。。。

・ニフティクラウドmobile backend(mBaaS)の登録、初期設定(アプリケーションキー、クライアントキーの取得)に関しては下記の記事をご確認ください

mBaaS利用登録

・Monacaの登録に関しては下記の記事をご確認ください

Monaca利用登録

またMonacaに関してはここで公開されているニフティクラウドmobile backendのJSSDKのncmb.min.jsを下記のように配置してください

スクリーンショット 2015-12-12 14.22.31.png

下記のようにMonacaコンポーネント類を導入して下さい

スクリーンショット 2015-12-12 14.23.11.png

・OpenStreetMapに関しては何も設定がいらない!(一番素晴らしい!)

そして,Monaca上のwwwフォルダ直下にindex.htmlを、www>js配下にapp.jsをそれぞれ配置します。その中身は以下になります。


index.html

<!DOCTYPE HTML>

<html>
<head>
<meta charset="utf-8">
<script type="text/javascript" src="js/ncmb.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<script src="components/loader.js"></script>
<link rel="stylesheet" href="components/loader.css">
<link rel="stylesheet" href="css/style.css">
<script type="text/javascript" src="js/app.js"></script>
<script type="text/javascript" src="http://www.openlayers.org/api/OpenLayers.js"></script>
</head>
<body>
<script type="text/javascript">
navigator.geolocation.getCurrentPosition(onGeoSuccess, onGeoError, geoOption);
</script>

<button onclick="save_geopoint()">ポイントを保存する</button>
<button onclick ="find_geopoint()" style="width:100%;">ポイントを見る</button>

<div class="wrapper">
<div id="canvas" style="width:100%; height:400px"></div>
</div>
</body>
</html>



app.js

//各種設定値記載

var current;
var YOUR_APP_KEY = "登録後アプリ作成した場合に自動で発行されますのでそれを貼り付け";
var YOUR_CLIENT_KEY = "登録後アプリ作成した場合に自動で発行されますのでそれを貼り付け";
var ncmb;
var map;

//ニフティクラウドmobile backendの準備
$(function(){
ncmb = new NCMB(YOUR_APP_KEY,YOUR_CLIENT_KEY);
});

//OSMの描画
function writemap(lat,lon) {
map = new OpenLayers.Map("canvas");
var mapnik = new OpenLayers.Layer.OSM();
map.addLayer(mapnik);
console.log(lat+":"+lon+":");
var lonLat = new OpenLayers.LonLat(lat,lon)
.transform(
new OpenLayers.Projection("EPSG:4326"),
new OpenLayers.Projection("EPSG:900913")
);
map.setCenter(lonLat, 15);
var markers = new OpenLayers.Layer.Markers("Markers");
map.addLayer(markers);

var marker = new OpenLayers.Marker(
new OpenLayers.LonLat(lat,lon)
.transform(
new OpenLayers.Projection("EPSG:4326"),
new OpenLayers.Projection("EPSG:900913")
)
);
markers.addMarker(marker);
}

//OSMの描画時に位置情報取得に成功した場合のコールバック
var onGeoSuccess = function(position){
current = new CurrentPoint();
current.geopoint = position.coords; //位置情報を保存する
writemap(current.geopoint.longitude,current.geopoint.latitude);
};

//位置情報取得に失敗した場合のコールバック
var onGeoError = function(error){
console.log("現在位置を取得できませんでした");
};

//位置情報取得時に設定するオプション
var geoOption = {
timeout: 6000
};

//現在地を保持するクラスを作成
function CurrentPoint(){
geopoint=null; //端末の位置情報を保持する
}

//現在地をポイントとして登録する
function save_geopoint(){
navigator.geolocation.getCurrentPosition(onSaveSuccess, onGeoError, geoOption);
console.log("save_geopoint");
}

//ポイントの登録時に位置情報取得に成功した場合のコールバック
var onSaveSuccess = function(location){
navigator.notification.prompt(
' ', // メッセージ
onPrompt, // 呼び出すコールバック
'ポンイントの登録', // タイトル
['登録','やめる'], // ボタンのラベル名
'ポイント名' // デフォルトのテキスト
);

function onPrompt(results) {
current.geopoint = location.coords;
var geoPoint = new ncmb.GeoPoint(location.coords.latitude, location.coords.longitude);
console.log(location.coords.latitude + ":" + location.coords.longitude);
var Places = ncmb.DataStore("PlacePoints");
var point = new Places();
point.set("name",results.input1);
point.set("geo", geoPoint);

point.save()
.then(function(){})
.catch(function(err){// エラー処理
});
}

};

//登録されたポイントを引き出し地図上に表示する
function find_geopoint(){
navigator.geolocation.getCurrentPosition(onFindSuccess, onGeoError, geoOption);
console.log("find_geopoint");
}

//登録ポイントの表示時に位置情報取得に成功した場合のコールバック
var onFindSuccess = function(location){
current.geopoint = location.coords;
var geoPoint = new ncmb.GeoPoint(location.coords.latitude, location.coords.longitude);
console.log("findpoints:"+location.coords.latitude + ":" + location.coords.longitude);
var PlacePointsClass = ncmb.DataStore("PlacePoints");
//ニフティクラウド mobile backendにアクセスして検索開始位置を指定
PlacePointsClass.withinKilometers("geo", geoPoint, 5)
.fetchAll()
.then(function(results){
var data = [];
for (var i = 0; i < results.length; i++) {
var result = results[i];
var markers = new OpenLayers.Layer.Markers("Markers");
map.addLayer(markers);
var regist_location = result.get("geo");
var marker = new OpenLayers.Marker(
new OpenLayers.LonLat(regist_location.longitude,regist_location.latitude)
.transform(
new OpenLayers.Projection("EPSG:4326"),
new OpenLayers.Projection("EPSG:900913")
)
);
markers.addMarker(marker);
}
});

};


これでアプリはできました。まさに手でオープンデータのDBを作れるアプリ、本当に便利かは置いておいて、みんなで○○Mapを作る場合には重宝しそうです。明日は実際にこのアプリを使った○○mapを作った話を書きます。