2008-08-11
どうも、カヤックモバイル$のaragaです。
PHPで携帯の位置情報を簡単に取り扱うことができるライブラリを作りました。
巷で話題沸騰中の先日リリースした「おひらきNAVI」で作ったものですが、ウノウさんが同様のネタ「PHPで携帯位置情報を扱うライブラリ「Geomobilejp_Converter」を作りました 」で沢山ブックマークされていたので、便乗して公開することにしました。
GPSに関することはウノウ中村さんの「携帯GPSの基礎知識たち」が非常に解りやすくまとまっているので参考にしていただけると良いかと思います。
位置情報からエリア情報の取得は、「SimpleAPIの最寄り駅Webサービス」を使用させていただきました。
使い方の紹介
※ キャリア情報にNet_UserAgent_Mobileを使用しています。
- 各キャリアのGPS取得用タグを作成する
<?php
require_once '/path/to/Mobile/GPS.php';
$gps =& Mobile_GPS::factory();
?>
<?php echo $gps->createFormTag(link_url("", "action=getPlace"), "get"); ?>
<input type="submit" value="位置情報を取得する">
</form>
- 送られてきた位置情報を使用してSimpleAPIを使用する
<?php
require_once '/path/to/Mobile/GPS.php';
require_once '/path/to/SimpleAPI/Station.php';
$gps =& Mobile_GPS::factory();
$gps->load();
if ($gps->getLat() && $gps->getLon()) {
$simpleApi =& new SimpleApi_Station($gps->getLon(), $gps->getLat());
$simpleApi->load();
$nearest_station = $simpleApi->stations[0];
}
?>
<dl>
<dd>駅名</dd><dt><?= $nearest_station['name'] ?></dt>
<dd>路線</dd><dt><?= $nearest_station['line'] ?></dt>
<dd>市町村</dd><dt><?= $nearest_station['city'] ?></dt>
<dd>都道府県</dd><dt><?= $nearest_station['prefecture'] ?></dt>
<dd>直線距離</dd><dt><?= $nearest_station['distance'] ?></dt>
<dd>徒歩持間</dd><dt><?= $nearest_station['traveltime'] ?></dt>
</dl>
まだまだ、GPS対応機種チェック等が必要かと思いますが、それはNet_UserAgent_Mobileなど各自の管理方法でお願いします。
残念ながらあらゆる機種テストはできなかったので、これじゃ動かねーよ!って言うのがありましたら、つっこみ大歓迎です。
ソース
カヤックでは携帯サイトのノウハウにたいして造詣の深い方や、日本一面白い携帯サイトを作る情熱のあるプログラマを募集しています!
2008-07-23
perl のイベントで空気を読まず Flash についての発表をしたり、Ajax のテーマの原稿で空気を読まず Flash について書いたりしている村瀬です。こんにちは。
先日 adobe が AMF (Action Message Format) の仕様を公開してくれたので、それではと perl で AMF パーサーを書いてみました。
この中の Data::AMF が AMF のデータ部分のみをパースするモジュール。Data::AMF::Packet が Flash Remoting などでつかわれる AMF パケットをパースするモジュールとなっています。
ということで、Data::AMF::Packet を使用すれば Flash Remoting のサーバーサイドを開発することはできるのですが、AMF パケットを素で扱うと若干面倒な実装をする必要があります。そこで、あわせて Catalyst 用の Flash Remoting 専用コントローラも開発しました。
まず、Catalyst::Controller のかわりに Catalyst::Controller::FlashRemoting を継承します。
package MyApp::Controller::Root;
use strict;
use warnings;
use base 'Catalyst::Controller::FlashRemoting';
次にゲートウェイとなるアクションに :AMFGateway という属性をつけます。
この場合 /gateway というURLをゲートウェイにしたいとすると、
sub gateway :Local :AMFGateway { }
というアクションを作成します。:AMFGateway という属性をつける以外は Catalyst の通常のアクションと変わりません。
このゲートウェイ用のアクションは AMF リクエストをパースし、それをもとにリクエストにあったメソッドを自動的に呼び出します。そしてそのメソッドの返り値をまたAMFにシリアライズし、レスポンスを作ります。
メソッドを作るには :AMFMethod という属性をつけた関数をゲートウェイと同じ名前空間につくります。
sub echo :AMFGateway('echo') {
my ($self, $c, $arg) = @_;
return $arg
}
:AMFGateway という属性に引数で渡した文字列 (ここではAMFGateway('echo')としてますのでechoがその文字列になります) が AMF のメソッド名になります。 ここは省略可能で、省略した場合はそのメソッドの関数名自体が使用されます。
すなわち上の例は
sub echo :AMFGateway {
my ($self, $c, $arg) = @_;
return $arg
}
と書くこともできます。
今作ったコントローラの全体像を貼ってみます。
package MyApp::Controller::Root;
use strict;
use warnings;
use base 'Catalyst::Controller::FlashRemoting';
sub gateway :Local :AMFGateway { }
sub echo :AMFMethod {
my ($self, $c, $args) = @_;
return $args;
}
1;
これだけのコードで、Flash Remoting サーバーの出来上がりです。echo は受けたリクエストをそのままオウム返しするメソッドです。
簡単ですね!
Catalyst を普段使っている人であれば一瞬で Flash Remoting のサーバーを作ることができるでしょう。皆さんもRemotingサーバーが必要なときはぜひ使ってみてくださいね!
カヤックでは Flash のバッドノウハウにたいして造詣の深い方や AMF のみならず RTMP にも詳しい方を募集しています!
2008-07-22
最近気づいたんですが、jQuery.dataが結構便利だと思うので紹介してみたいと思います。
(function($) {
var name_space = 'name_space';
$.fn[name_space] = function(options) {
var elements = this;
var settings = $.extend({
}, options);
elements.each(function() {
var t = this;
$.data(t, name_space, {});
$(t).hover(function () {
var obj = $.data(this, name_space);
obj.status = 'over';
$.data(self, name_space, obj);
}, function () {
var obj = $.data(this, name_space);
obj.status = 'out';
$.data(self, name_space, obj);
});
});
return this;
};
})(jQuery);
これは単純にmouseoverしているかどうかを設定しているだけですが、「ある要素がクリックされているか否か」、「ある要素の値が設定されているか否か」をtagの種類によらず保持できるのはそれなりに使い道があると思います
また、保持できる内容がobjectなので、html element等をそのまま保持できるのも魅力です。
//最初のa tagに最後のa tagの参照を保持
$.data($('a:first').get(0), 'hoge', $('a:last').get(0));
//保持されているa tagのhrefを返す
$.data($('a:first').get(0), 'hoge').href;
//->"http://bm11.kayac.com/"
2008-07-17
今日はJSでVista Sidebar gadgetを作る際のTipsを紹介したいと思います
- ライブラリは遠慮なく使う
規模も小さく、隔離された環境なので影響範囲の大きいライブラリ等を使っても問題が少ないです。過去にPrototype.jsやjQueryを使用しましたが、問題は起きませんでした。
- データの重さは気にしない
gadgetに同封してあるデータは、数MBなら一瞬で表示されます
- 処理速度は気にする
常に表示され続けるので重い処理は避けましょう
- swfを使用する場合、ExternalInterface.addCallbackが必要な処理を行わない
ExternalInterface.addCallbackされたmethodをJSから呼んでも反応しませんでした。localのswfをブラウザで開くと同様の動作になるため、flash側の仕様ではないかと想像しています。また、いくつか配布されているgadgetを確認しましたが、ExternalInterface.addCallbackを使用していると思われるgadgetはありませんでした
- できること、できないことを早めに見極める
「面倒かな?」と思うことが簡単だったり(Flyoutの動的な形変換は標準で可能)、「簡単だろう」と思うことが不可能だったりします(JSから動的にdocOutする)
- 無理してDTDに従わない
interfaceはHTMLっぽいですが、独自タグとかあるのでそもそもDTDとか気にしなくていいです。SEO対策とかも当然不要なので、デザインはほぼ画像のみでOKです
- WebアプリとWindowsアプリのいいとこ取りをする
shellアクセスや、速度的な意味ではWindowsアプリ、ネット上へ自由にアクセスできる、HTML等で表示を簡単に切り替えられるのはWebアプリといいとこ取りできます
- IE7で動けばOK
クロスブラウザに関しては基本的に一切考慮不要です。Live gadget版は別に作りましょう
- 既存のコードを眺める
sidebar gadgetで難読化されたコードはほとんどないです。実データをweb上からダウンロードするタイプのgadgetでも大抵JSはそのままなので、普通に読めます
- セキュリティに気をつける
sidebar gadgetはshellアクセスが可能なので、不正なJSONを落としてevalしたらシステムのっとられます
- 位置調整は別アプリで
やはりfirebugは便利です。細かい位置調整等はsidebar内ではなく別アプリを使いましょう
- 要素はできるだけ背景に埋め込む(副笑い実装)
ボタン、リンク等でも静的な部分は背景画像として保持し、上に透明なgifを貼ってclick取るほうがいろいろ楽です。clickもa tagではなく、img tagのcursorを変更してリンクっぽく見せるほうが実装が楽です
body {
background: no-repeat url('background.png');
width: 130px;
height: 170px;
}
body * {
position: absolute;
border: none;
margin: 0px;
padding: 0px;
}
- 透過pngに注意
通常は問題なくても古いアプリを動かすと透過部分がピンクになる場合があります(vistaの表示モードが切り替わる?)
コードがほとんどなくて恐縮ですが、参考にしていただけると幸いです
2008-07-15
最近blogpartsでもjQueryを使うようになったので、blogpartsでjQueryを使うときのコードをまとめてみました。
(function () {
//script tagのsrcの先頭部分を記述(自分のscript tagを取得するのに使用)
var domain = 'http://example.com/bp/';
//asから呼び出されるときの名前を指定(外部からはこの名前のみ見える)
var name_space = 'blogparts_name_spase';
//各ライブラリをfunction scopeへ展開
var lib = loadLib(), $ = lib.$, jQuery = lib.jQuery, swfobject = lib.swfobject;
//読み込まれた時点での最後のscript tagを取得
var $script = $('script[src^="'+domain+'"]:last');
$(function () {
var options = (function (s) {
var param = {};
var dec = decodeURIComponent;
//自身のscript tagに書かれた引数を取得
//(srcの「#」以降にquery string形式で記述されていることを想定)
$.each(s.attr('src').split('#').pop().split('&'), function () {
var kv = (this + '').split('=');
param[dec(kv[0])] = dec(kv[1]);
} );
return $.extend({
//引数の初期値を設定
'key' : 'value'
}, param);
})($script);
//内部methodを記述。swfを出力する場合$scriptを基点に出力
window[name_spase] = {
//外部に公開する(asから呼ばれる)methodを記述
'call_method' : function () {
}
};
});
function loadLib() {
//各種必要なライブラリのsourceを記述(swfobject等)
//jQuery本体のsourceを記述
//noConflictでjQueryの衝突を回避。ここで代入されているjQueryや$は、先頭部分でvar libと一緒に宣言されているもの(function scope)
jQuery = window.jQuery.noConflict( true );
$ = jQuery;
//使用するjQuery Pluginがあればここに記述
//読み込んだライブラリを返す。これ以外にも読み込んだものがあれば追記する
return {'$' : $, 'jQuery' : jQuery, 'swfobject' : swfobject};
};
})();
上記のコードは以下の点に気をつけています。
- 名前空間を汚さない (上記コードは「name_space」に指定した名前と、一時的にwindow.jQueryを使用)
- 複数のversionのjQueryが読み込まれていても衝突しない (jQuery.noConflict( true )で先に読み込まれたjQuery objectを戻す)
- ライブラリを全体のソースの最後に読み込む (ファイルの先頭にライブラリのコードがあると読みにくい)
- jQuery Pluginの使用も想定 (window.jQueryを参照するようなPluginは使用できませんが、一般的なつくりのものなら使用可能)
blogpartsでは性質上環境を想定できない場合が多く、場合によってはprototype.jsと同時に読み込まれることもあるため依存性の低いjQueryは非常におすすめです。
