地図とIT…便利な連携ができそうです。
自分の居場所を知られたくないケースはよくありますが、知ってほしいケースもあります。
例えば
- 待ち合わせで今いる場所を正確に伝えたい(今ここにいるよーという声)
- 災害時に報告して安否を通達したい(大丈夫ですよーという声)
- ラウンダー業務の証拠づくり(現場で仕事していますよーという声)
今回はOpenStreetMap 、OpenLayers、OpenStreetMap Nominatim を使って、いま・どこで・どうなっているかを記録して通達する仕組みを作ってみました。記録したデータはkintoneに貯めておきます。
できあがり
スマートフォンのkintoneアプリから保存、閲覧したkintone画面
だれが、いつ、どこにいたかが早わかり
素材
OpenStreetMap
道路地図などの地理情報データを誰でも無償で利用できるサービスで、APIも豊富です。Google Mapも無料で利用しているのになぜ?と思われがちですが、APIを使う際にはライセンス(有償)が必要なことがあるようです。
OpenLayers
ブラウザに様々な地図を、簡単に重ね合わせて表示できるオープンソースのJavaScriptライブラリです。
OpenStreetMap Nominatim
geocoding ができる WebAPIで、緯度・経度から場所を取得できます。
kintone
kintoneは、業務システムをエンドユーザーが素早く作れる&使えるクラウドサービスで、cybozu developer networkに載っているようにREST API、JavaScript API もあるので、いろいろカスタマイズできちゃいます。
使ったAPI、function、method
- ol.Map
- ol.layer.Tile
- ol.View
- ol.source.OSM
- ol.proj.transform
- (OpenLayers).addOverlay
- kintone.app.getId
- kintone.api.url
- kintone.api
- kintone.[mobile.]app.record.getFieldElement
- kintone.app.record.setFieldShown
- kintone.mobile.app.getHeaderSpaceElement
- kintone.app.record.getSpaceElement
- kintone.events.on
- kintone.proxy
- kintone.Promise
準備
- kintone開発者ライセンスを取得 ※developer networkへのメンバー必要
- Githubでプログラムなどのダウンロード
-
スマホ用kintoneアプリのインストール
- kintoneのURLを指定するとブラウザからも利用可能
作り方
- kintoneにログイン後にアプリテンプレートの読み込み
- Githubでプログラム一式のダウンロードにある「kintone-osmPoint.zip」をkintoneに読み込む ※ ファイルからアプリテンプレートを読み込む方法
- テンプレートからアプリを作成
- スマホからログインして使ってみる
- レコード追加する
kintoneからの挙動
- レコードを追加したら、位置情報を取得して保存
- 緯度経度情報を元にOpenStreetMapで地図を表示
- 緯度経度情報を元にNominatimを使い逆ジオゴ-ディング
- 中心部にピント、登録者名+日時を表示
- 緯度経度はブラウザから編集できないように非表示
プログラム
https://github.com/ushiront/kintone-osmPoint
Point.1
var appId = kintone.app.getId() ? kintone.app.getId() :
Number(location.pathname.replace(/\/k\/m\//, "").split("/")[0]);
スマートフォン用のJavaScriptではアプリIDを取得できないのでブラウザのアドレスから取得。
Point.2
var hideGroupFields = function(event) {
if (event.type.match(/^mobile./)) {
kintone.mobile.app.record.setFieldShown("Lat", false);
kintone.mobile.app.record.setFieldShown("Lng", false);
} else {
if (kintone.app.record.getFieldElement("Lat") === "undefined") { return; }
if (kintone.app.record.getFieldElement("Lng") === "undefined") { return; }
if (kintone.app.record.getFieldElement("Title") === "undefined") { return; }
if (kintone.app.record.getFieldElement("Address") === "undefined") { return; }
kintone.app.record.setFieldShown("Lat", false);
kintone.app.record.setFieldShown("Lng", false);
}
event.record["Title"]["disabled"] = true;
event.record["Address"]["disabled"] = true;
};
フィールドの表示、非表示、非アクティブ化。
スマートフォン用のJavaScriptでは要素が取れないのでPC用のみでエラーチェック。
Point.3
// OpenStreetMap and OpenLayers
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: ol.proj.fromLonLat([lng, lat]),
zoom: osmPosition.defZoom
})
});
// Append Overlay
var pos = ol.proj.transform([lng, lat], 'EPSG:4326', 'EPSG:3857');
// Marker pin
var imgElement = document.createElement('img');
var imgSrc = 'data:image/png;base64,base64 imagedata';
imgElement.setAttribute('src', imgSrc);
var marker = new ol.Overlay({
position: pos,
element: imgElement,
stopEvent: false,
positioning: 'center-center'
});
map.addOverlay(marker);
中心部の緯度経度、縮尺を指定して地図を取得
pin画像をレイヤ追加
Point.4
// kintone promise
return new kintone.Promise(function(resolve, reject) {
// geolocation API
navigator.geolocation.getCurrentPosition(function(position) {
event.record["Lat"]["value"] = position.coords.latitude.toFixed(7);
event.record["Lng"]["value"] = position.coords.longitude.toFixed(7);
var url = "https://nominatim.openstreetmap.org/reverse?format=json";
url += "&lat=" + event.record["Lat"]["value"];
url += "&lon=" + event.record["Lng"]["value"];
// Get address by Re-Geocording
kintone.proxy(url, 'GET', {}, {}).then(function(args) {
var resp = JSON.parse(args[0]);
var respValue = {
state: resp.address.state ? resp.address.state : "",
city: resp.address.city ? resp.address.city : "",
traffic_signals: resp.address.traffic_signals ? resp.address.traffic_signals : "",
country: resp.address.country ? resp.address.country : ""
};
event.record["Address"]["value"] =
respValue.state + respValue.city + respValue.traffic_signals + "(" + respValue.country + ")";
resolve(event);
}, function(error) {
console.log(error);
reject(event);
});
}, function(error) {
// error event
reject(event);
});
});
レコード保存時に位置情報を取得し、住所を取得
※位置情報は詳細特定をされないように桁指定
kintone.Promise, kintone.proxyを利用して外部サービスを実行
今後やってみたいこと
- スタッフの最新情報を表示
- トレース
- 地図に関するiPhoneAppを作ってみたい