Framework7 でモバイルWebを開発するとHTML5/JavaScript/CSSを使ってiOSやMaterialデザインのネイティブに近いUIを作ることができます。またW3Cが策定しているHTML5のデバイスAPIを活用すれば、ネイティブのAPIをコールしなくてもHTML5経由でハードウェアの制御を行うこともできます。簡単なところからGeolocation API で緯度経度情報を取得して遊んでみようと思います。
参考
デモアプリ リポジトリはこちら です。デモはこちら から実行できます。日本国内だと現在位置の緯度経度から計算できる国コードはJP、通貨コードはJPYだけなのであまりおもしい結果が出ませんが、任意の緯度・経度を手動で入力すれば逆ジオコーディングで位置情報から国コードや通貨コードを取得することができます。
緯度・経度を入力する 緯度経度をGeolocation APIを使わずにフォームへ手動入力してみます。「位置を入力する」タブからテスト用にアゼルバイジャンの緯度・経度を設定します。
緯度: 40.406605
経度: 49.804306
フォームに入力したデータはForm Data にあるようにJSON形式で取得することができます。
index.html <form id ="my-form" class ="list-block" > <ul > <li > <div class ="item-content" > <div class ="item-media" > <i class ="icon icon-form-settings" > </i > </div > <div class ="item-inner" > <div class ="item-title label" > 緯度</div > <div class ="item-input" > <input name ="latitude" type ="text" placeholder ="緯度を入力" > </div > </div > </div > </li >
「入力値を使う」ボタンをタップするとapp.formToJSONからJSON形式でフォームの値を取得できます。
src/client/js/index.js $$('.form-to-json' ).on('click' , function ( ) { var formData = app.formToJSON('#my-form' ); if (!isNumber(formData.latitude) || !isNumber(formData.longitude)) { return app.alert('数値を入力してください。' ); } latLng = new google.maps.LatLng(formData.latitude, formData.longitude); geocodeAction(latLng); });
緯度・経度の現在位置を取得 W3CのGeolocation API を使います。navigator.geolocation.watchPosition の場合はデバイスの位置が変わる度に位置情報を取得しているため、電池の消耗が激しそうです。
画面のボタンを押したときだけnavigator.geolocation.getCurrentPosition を使い現在の位置情報を取得するようにします。
src/client/js/index.js $$('#location_btn' ).on('click' , function ( ) { if (navigator.geolocation) { app.showIndicator(); navigator.geolocation.getCurrentPosition( function (position ) { latLng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude); ...
逆ジオコーディング 「現在位置を使う」または「位置を入力する」のタブから取得した緯度・経度情報を使って逆ジーコーディング をします。
国コードの取得 Google Maps Javascript API Google Maps Javascript API
の逆ジオコーディング を使います。
src/client/js/index.js function getCountryNameCode (latLng, callback ) { var geocoder = new google.maps.Geocoder(); var retval = {}; var location = {lat : latLng.lat(), lng : latLng.lng()}; geocoder.geocode({'location' : location}, function (results, status ) { if (status !== google.maps.GeocoderStatus.OK) return callback(new Error ("can't get goecoder" )); _.forEach(results[0 ].address_components, function (comp ) { if (comp.types[0 ] == "country" ) { retval['short' ] = comp.short_name; retval['long' ] = comp.long_name; } }); if (!retval) return callback(new Error ("can't get country code" )); else return callback(null , retval); }); }
address_component.types[0] == "country"のときに、address_component.short_nameに国コードが入っています。
long_name: 日本
short_name: JP
参考
通貨コードの取得 通貨コードはGoogle Maps APIの逆ジオコーディングでも取得できなかったので、Open KnowledgeのFrictionless Open Data からComprehensive country codes: ISO 3166, ITU, ISO 4217 currency codes and many more の変換表を使うことにします。データをJSON形式でダウンロード します。
日本を例にすると国コードや通貨コードの他にもFIFAやIOCなど様々な日本のコードが定義されています。
country-codes.json "name":"Japan","name_fr":"Japon","ISO3166-1-Alpha-2":"JP","ISO3166-1-Alpha-3":"JPN","ISO3166-1-numeric":"392","ITU":"J","MARC":"ja","WMO":"JP","DS":"J","Dial":"81","FIFA":"JPN","FIPS":"JA","GAUL":"126","IOC":"JPN","currency_alphabetic_code":"JPY","currency_country_name":"JAPAN","currency_minor_unit":"0","currency_name":"Yen","currency_numeric_code":"392","is_independent":"Yes"}
ISO3166-1-Alpha-2: JP
currency_alphabetic_code: JPY
Expressで簡単なAPIサーバーを用意して、ここからダウンロードしたJSONデータ をクエリするようにしました。
クライアントサイドからはGoecoderから取得したshort_name(JP)を条件にしてサーバーサイドのAPIを実行します。
src/client/js/index.js var q = '/api/currency/' + countryShortName;app.showIndicator(); $$.get(q, function (data ) { app.hideIndicator(); data = JSON .parse(data); currencyCode = data.currency_code; $$('#currency_code' ).text(currencyCode); });
サーバーサイドのapp.js では引数のISO3166-1-Alpha-2(JP)からcurrency_alphabetic_code(JPY)をlodash の_.find を使ってクエリします。
src/server/app.js "use strict" ;var express = require ('express' ), path = require ('path' ), bodyParser = require ('body-parser' ), _ = require ('lodash' ), countryCodes = require ('./country-codes.json' ), router = express.Router(), app = express(); app.use(express.static(path.join(__dirname,'..' ,'..' ,'dist' ))); app.use(bodyParser.urlencoded({ extended : true })); app.use(bodyParser.json()); router.get('/currency/:country' , function (req, res ) { var currency_code = _.result(_.find(countryCodes, 'ISO3166-1-Alpha-2' , req.params.country), 'currency_alphabetic_code' ); res.json({ currency_code : currency_code}); }); app.use('/api' , router); var server = app.listen(3000 , function ( ) { var host = server.address().address, port = server.address().port; console .log('Example app listening at http://%s:%s' , host, port); });
為替レート メニューの「為替レート」をタップします。取得した通貨コードを使ってYQLから為替レートを を取得してみます。この例ではアゼルバイジャン・マナト の為替レートです。
1ドル、1ユーロ、1円の現地通貨のレートをYQL のyahoo.finance.xchangeからクエリします。
index.js function currencyRate ( ) { var base_url = 'https://query.yahooapis.com/v1/public/yql' ; var query = 'select%20*%20from%20yahoo.finance.xchange%20where%20pair%20in%20("' +'USD' +currencyCode+',' +'EUR' +currencyCode+',' +'JPY' +currencyCode+'")' ; var q = base_url + '?q=' + query + '&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys' ; app.showIndicator(); $$.get(q, function (data ) { app.hideIndicator(); data = JSON .parse(data); if (!data.query || !data.query.results) return ; var rate = data.query.results.rate; console .log(rate); rate.forEach(buildRate); }); }