Ruby on RailsでのGPS連携について
GPSで取得した現在地から、Ruby on RailsのDBに登録した複数の地点までの距離をそれぞれ計算し、下記画面のように一覧で表示させるモバイル機能を開発した。
Ruby on RailsとGPS連携の概要は以下のようになっている。
1. Railsのビューの<head></head>にインクルードするjavascriptを記述。
2. インクルードしたapplication.jsにGoogleからライブラリを取得する記述。
3. GoogleAPIにより現在地の取得。
4. Railsのビューの中にGoogleAPIのCallBack関数を記述。
5. CallBack関数で実行されるyorimichiList関数をapplication.jsに記述。
6. 取得した緯度、経度の値をRailsのコントローラーに明記した"yorimichi_sort"アクションにPOSTメソッドで渡す。
7. Railsの"yorimichi_sort"アクションにパラメーターで渡された緯度、経度とデータベースに登録されたスポットの緯度、経度の値を用いて現在地から各スポットまでの直線距離を算出、距離で昇順にソート。
8. ソートされたスポットの距離がjavascriptに返される。
9. Railsのビューの指定したタグに7.のRailsアクションでソートされたスポットの一覧が表示される。
1.Railsのビューの<head></head>内でインクルードするjavascriptを記述。
http://www.google.com/jsapi?key=hogehoge のhogehogeにはGoogleAPIのキーを記述。
(※キーの取得はGoogle Maps APIのページを参照)
<head> <title>GPSDemo</title> <metahttp-equiv="Content-Type" content="text/html;charset=UTF-8" /> <metahttp-equiv="Content-Style-Type" content="text/css" /> <metahttp-equiv="Content-Script-Type" content="text/javascript"/> <meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1,maximum-scale=1" /> <scripttype="text/javascript" src="http://www.google.com/jsapi?key=hogehoge"></script> <%= stylesheet_link_tag'default', :media => 'screen' %> <%= stylesheet_link_tag 'hvga', :media=> 'only screen and (min-device-width: 320px) and (max-device-width:480px)' %> <%= stylesheet_link_tag 'xga-landscape',:media => "only screen and(min-device-width : 768px) and(max-device-width : 1024px) and (orientation : landscape)" %> <%= stylesheet_link_tag'xga-portrait.css', :media => "only screen and (min-device-width :768px) and (max-device-width : 1024px) and (orientation : portrait)" %> <%#=javascript_include_tag :defaults %> <%=javascript_include_tag 'application' %> <%=javascript_include_tag 'iui' %> <%= csrf_meta_tag %> <%= yield(:javascripts)if content_for?(:javascripts) %> </head>
2. インクルードしたapplication.jsにGoogleからライブラリを取得する記述。
google.load("maps","3",{other_params :'sensor=true'}); google.load("jquery","1.4"); google.load("gdata","2");
3.GoogleAPIにより現在地の取得を行う。
function getClientLocation(stLatitude, stLongitude) { if(navigator.geolocation){ navigator.geolocation.getCurrentPosition( function (val){ getLocationCallBack(val.coords.latitude,val.coords.longitude); gpsInfoDisplay(val.coords.latitude,val.coords.longitude,val.coords.accuracy); }, function(){ getLocationCallBack(stLatitude, stLongitude); }, {maximumAge: 0,enableHighAccuracy: true} ) }else{ getLocationCallBack(stLatitude, stLongitude); } }
4.Railsのビューの中にGoogleAPIのCallBack関数を記述。
<% content_for :javascripts do %> <script type="text/javascript"> $(document).ready(function(){ google.setOnLoadCallback(getClientLocation('<%=@organization.st_latitude %>','<%= @organization.st_longitude %>')); getLocationCallBack =function(lat, longi){ yorimichiList(lat,longi); } }) </script> <% end %>
5.CallBack関数で実行されるyorimichiList関数をapplication.jsに記述。
取得した緯度、経度の値をRailsのコントローラーに明記した"yorimichi_sort"アクションにPOSTメソッドで渡す。
function yorimichiList(latitude,longitude){ var division_id =document.getElementById("division_id").value; $.post("yorimichi_sort", {division_id: division_id, lat:latitude, longi: longitude}, function(result){ $("#location").html(result); }) }
6. 緯度、経度の値を用いて現在地から各スポットまでの直線距離を算出、距離で昇順にソート。
Railsの"yorimichi_sort"アクションにパラメーターで渡された緯度、経度とデータベースに登録されたスポットの緯度、経度の値を用いて現在地から各スポットまでの直線距離を算出、距離で昇順にソート。
def yorimichi_sort @division =Division.find(params[:division_id]) start_lat = params[:lat].to_f start_longi = params[:longi].to_f @start_end = @organization.distance(start_lat,start_longi) @spot_distance_ary = [] @division.spot_divisions.each do |spot_division| spot = spot_division.spot st_mid_distance = spot.distance(start_lat,start_longi) mid_end_distance = spot.distance(@organization.dest_latitude,@organization.dest_longitude) yorimichi_total = st_mid_distance + mid_end_distance @spot_distance_ary<< [yorimichi_total, spot, st_mid_distance,mid_end_distance] end @spot_distance_ary.sort_by!{|yorimichi_total,spot, st_mid_distance, mid_end_distance| st_mid_distance} if @organization.means_route == 'DRIVING' difflag = '&dirflg=d' elsif @organization.means_route == 'WALKING' difflag = '&dirflg=w' end @dest_map_url ="http://maps.google.co.jp/maps?saddr=" + start_lat.to_s + ',' +start_longi.to_s + '&daddr=' + @organization.dest_latitude.to_s + ',' +@organization.dest_longitude.to_s + difflag render :partial => "spot_list", :layout => false end defdistance(lat,longi) dp = (self.latitude - lat).abs dr = (self.longitude - longi).abs p= ((self.latitude + lat) / 2)*Math::PI/180 t= (1-0.006674*Math.sin(p)*Math.sin(p)) m= 6334834 / (Math::sqrt(t*t*t)) n= 6377397 / (Math::sqrt(t)) return((Math::sqrt((m*dp*Math::PI/180)*(m*dp*Math::PI/180)+(n*Math.cos(p)*dr*Math::PI/180)*(n*Math.cos(p)*dr*Math::PI/180)))/100).round/10.0 end
7.下記のresultにソートされたスポットの距離が返される。
function yorimichiList(latitude,longitude){ var division_id =document.getElementById("division_id").value; $.post("yorimichi_sort", {division_id: division_id, lat:latitude, longi: longitude}, function(result){ $("#location").html(result); }) }
8.スポットの一覧が表示
Railsのビューに以下のように明記したid=locationのタグに4.のRailsアクションでソートされたスポットの一覧が表示される。
<article id="location"> <p> </p> </article>
※上記の内容は、平成22年度「Ruby 人材育成によるビジネス利用拡大業務」で開発したシステムの概要を解説したものです。