ActionScript 3.0 , AIR , FLEXからCocoa, OpenGL
25 Feb
以前、名古屋のFxugにて少し発表した内容なんですが、ずっと記事にできてなかったので、今更ながらまとめます。
密かに前から社内用発表会のネタとして作ってはいたのですが、僕個人的にも、なかなか披露する機会がないまま、時間が過ぎてしまいました。
概要としては、
1. iPhone上でボタンをタップすると、AIR 2で作ったサーバーに、iPhoneからSocket経由で信号を送ります。
2. AIR 2のサーバーが、信号を受け取り、信号に応じた処理を行います。
これが作ったアプリのキャプチャです。
iPhoneとAIR 2サーバーの関係は、この通りです。
簡単に行ってしまえば、これだけです。
では、ここから説明します。
1. AIR 2のサーバー部分を作成
AIRでサーバーを作るには、UDPとTCPのサーバーがありますが、今回はTCPで通信するので、flash.net.ServerSocketクラスを使用します。
宣言〜受付開始
<pre>import flash.net.ServerSocket; // 接続してきたSocketを保持する var socks:Vector. = new Vector.(); // インスタンス生成 var server:ServerSocket = new ServerSocket(); // 接続時のイベントハンドラ作成 server.addEventListener(ServerSocketConnectEvent.CONNECT, serverSocketConnectHandler, false, 0, false); // 待ち受けポートを指定(43243番で受け付ける) server.bind(43243); // 待ち受け開始 server.listenen();</pre>
接続時:
function serverSocketConnectHandler(event:ServerSocketConnectEvent):void
{
// 接続してきたSocket
var socket:Socket = event.socket;
// 接続してきたSocketにデータを返すため、イベント設定
socket.addEventListener(ProgressEvent.SOCKET_DATA, receiveHandler, false, 0, false);
// 接続してきたSocketを保持する
socks.push(socket);
}
受信時:(本来は宛先を指定するべきだが、特に指定せず、全てのSocketに送信しています)
function receiveHandler(event:ProgressEvent):void
{
// データを送信したSocketを取得
var socket:Socket = event.target as Socket;
if(socket!=null) // nullチェック
{
// 受信データを取得
var recv:String = socket.readUTFBytes(socket.bytesAvailable);
// 操作対象のVideoPlayerを取得
var target:VideoPlayer = getCurrentVideo(); // 自作のメソッドです
// コマンドを取得し、操作を実行。コマンドを取得するため、indexOfを使っています。
if( recv.indexOf("prev") >= 0) {
setPos("prev");
} else if( recv.indexOf("next") >= 0) {
setPos("next");
} else if( recv.indexOf("play") >= 0) {
if( target.playing ) {
target.pause();
} else {
target.play();
}
}
}
}
AIRで作るサーバー周りは、こんなところです。エラー処理や切断時の処理などは書いてなくてごめんなさい。
iPhone側アプリケーションのSocket処理
では、次。iPhoneのほう。これも簡単な書き方でごめんなさいね。と、いうかCで最低限の実装しかしていないです。
TCPSendClient.m
接続:
-(void)connect:(NSString *)ip toPort:(NSInteger)port
{
if(_connected) // TCPSendClientが持っている、接続状態を保持する変数
{
return;
}
_connected = NO;
// IPアドレスを取得
servIP = [ip UTF8String];
// portを取得
servPort = port;
// socketが正しく生成できているかチェック
if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
{
NSLog(@"socket creation error.");
return;
}
// socketの設定
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr(servIP);
servAddr.sin_port = htons(servPort);
// 接続
if(connect(sock, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0)
{
NSLog(@"connect error.");
return;
}
_connected = YES;
NSLog(@"connect succeed.");
}
送信:
-(void)send:(NSString *)message
{
mes = [message UTF8String];
mesLen = strlen(mes);
// 送信
if(send(sock, mes, mesLen, 0) != mesLen) {
NSLog(@"send failed.");
}
}
ちなみに、
TCPSendClientクラスは、Socket処理を受け持つクラスで、自作しています。
TCPSendClient.hはこんな風に書いています。
#import <Foundation/Foundation.h>
#import <stdio.h>
#import <sys/socket.h>
#import <arpa/inet.h>
#import <stdlib.h>
#import <string.h>
#import <unistd.h>
@interface TCPSendClient : NSObject {
int sock;
struct sockaddr_in servAddr;
unsigned short servPort;
const char *servIP;
const char *mes;
unsigned int mesLen;
BOOL _connected;
}
-(void)connect:(NSString *)ip toPort:(NSInteger)port;
-(void)send:(NSString *)message;
-(void)close;
-(BOOL)getConnected;
@property(readonly) BOOL connected;
@end
このサンプルでは、このようにTCPSendClientを使っています。
PagerViewController.m
-(IBAction) processConnect:(id)sender // ボタンをタップした時のAction
{
if([connectSwitch isOn]) // これは、接続のon/offを切り替えるUISwitchです。
{
[sendc connect:@"10.0.2.1" toPort:43243]; // sendcというのがTCPSendClientです
stateField.text = @"connect";
}
else
{
[sendc close]; // 本文では紹介しなかったですが、切断します。
stateField.text = @"disconnect";
}
}
データ送信:
-(IBAction) btnUp:(id)sender // 各ボタンのTouchUpInsideと関連づけています。
{
isPress = NO;
prevValue = 0;
if( (UIButton*)sender == btn) // btnとは、一つ前の動画にフォーカスをあてるためのボタンです。
{
dir = @"prev";
[sendc send:dir];
}
else if((UIButton*)sender == nextBtn) { // nextBtnとは、一つ次の動画にフォーカスをあてるためのボタンです。
dir = @"next";
[sendc send:dir];
}
else if((UIButton*)sender == playBtn) { // playBtnとは、フォーカスがあたっている動画を再生するためのボタンです。
dir = @"play";
[sendc send:dir];
}
}
ちなみに、こちらがiPhoneアプリの画面です。(すごい地味ですね。。。笑えない)
Interface Builderのキャプチャです。
Macをルーターにする
最後に、iPhoneとAIRサーバーを接続するための設定をします。Macなら「インターネット共有」を使えば簡単にルーターにして連携させる事が可能です。こういうときに、一つのメーカーが作っている事が良い事に思えますね。
今回は、AirMac経由で共有します。
1. 「システム環境設定」を開く
2. 「共有」を開く
3. 「インターネット共有」を選択する
4. 「共有する接続回路」がAirMac以外であることを確認。なっていなければ変更します。
→iPhoneとMacをAirMac(無線)で接続する
5. 「インターネット共有」のチェックを入れると、共有を開始するか確認してきますので、開始をクリックします。すると、画面右のAirmacのアイコンがこのようになります。
開始順としては、AIRサーバーとiPhoneが接続する必要があるので、
1. Macをルーターにする
2. AIRサーバーアプリを起動する
3. iPhoneアプリを起動して接続する。
4. iPhone上で操作する。
というところです。
今回簡単に紹介しすぎててすみません。このままでわかりにくいなどご意見ありましたら整理した上で、ソース込みで全て公開します。
29 Nov
本当にものすごく久々の投稿になってしまいました。
先日、11/26に行われた、Spark勉強会で、Dynamic Sound Generationの発表をしてきたので、その資料をアップします。
(※再生には音楽ファイルを必要なので、各自用意して下さい。)
「フーリエ変換を使わない、エフェクトのかけかた」というタイトル通り、信号処理には本来フーリエ変換は欠かせないものですが、フーリエ変換の話しになると一気に敷居が高くなる(というか自分が今勉強している状態なので、この様な発表になりました。
ただ、やはりフーリエ変換を使えていない&勉強途中での発表になってしまったので、波形が途切れてしまっているところがあるようで、ぷつぷつと途切れる音が結構聴こえてしまいます。。。
あくまでご参考程度にしていただければと思います。
[ファイル構成について]
SoundGeneration.mxml:ラジオボタンやスライダーがついているView + 実際に音を鳴らすファイル
model/SoundObj.as:Dynamic Sound Generationを使って音楽を再生したり、エフェクトをかけたりするスクリプトを記述しているファイル。
SoundObj.asに関しては、mxmlでも使いやすいように、IMXMLObjectインターフェイスを実装しています。
[SoundObj.asの仕組み]
_currentEffectというプロパティを切り替えて、どのエフェクトをかけるのかを選択します。
extractメソッドを呼び出すたびに、bufferプロパティにデータを蓄えています。
これを使って、ディレイや逆再生を実現しています。
なお、逆再生に関しては、こちらが大変参考になります。
23 Jul
さて、7.22はadobeにてspark勉強会でした。
会社を早めに出勤して、そうそうに向かったのですが、若干の遅刻。
やっぱり時間は苦手だなあ。
到着すると、Adobeの方からFlash Playerやpixel Benderなどの紹介がありました。
pixel Benderは是非試してみたいのですが、あいにく僕が持っているのはMacBookなので、まだ試す事はできなさそうです。。
MovieClipだけでなく、動画にもエフェクトがつけれるらしいですし、さらには噂では音にもエフェクトをつけられるという話しを聞いているので、とても興味があるのですが。。
Flash Player10は、Dynamic Sound Generationや、縦書きテキストの対応など、とても期待をしております。
ただ、いづれも最先端過ぎるのか、文献が少ないので習得するのは大変そうですね。
あと、FlashのSEO対策は、外部XMLとかも検索対象にしてくれるようだ、という話しを聞けたので、今後FlashはSEOに弱い!という通説が覆りそうで、楽しみです。
で、発表会。
はじめは、主催者でもある、yossy@beintaractiveさん。
Spark Projectの今までの経緯と、Actionscriptで疑似スレッドを実現する、ActionScript Thread Library 1.0 (そうめん)の紹介をされていました。
非同期処理を処理の流れ通りに記述できたり、割り込み処理や例外処理など、使いこなすとかなりASの開発が便利になりそうでした。
次は、seagirlさんの「Genius Framework」のご紹介。
シンプルで使い勝手が良さそうでした。Flexの方は一度触られてみてはいかがでしょうか?
あとは、コマンドラインでスケルトンコードを作ってくれる機能は、かなり便利なんじゃないかと思っています。
つぎは、mutsuさんのFrocessing。
テキストの扱いとか、3Dとかが比較的書きやすそうなのと、これで覚えれば本家Processingも使えるようになりそうですので、一度触ってみたいですね。
つぎは、arkwさん。
今まで全く考えていなかったような深い、深すぎるフレームについての話しが聞けて、すごく勉強になりました。
そして、最近Dynamic Sound Genrerationに興味を持っている僕が特に楽しみにしていた、
どこかでみたようなおもちゃから繰り出される音には、ただただ感激するのみでした。
勉強になります!
これがspark projectにコミットされているだなんて。すごいですね。
あまりにも文献が少ないサウンド系の情報を充実させよう!と思っていらっしゃるようです。
僕も何か力になれればと思うのですが、なかなか壁は高そうです。
サイトは、ksakaiさんの発表。
Swfを埋め込む時のタグについてや今後の方向性など、詳しいレベルでご説明いただいて、とても勉強になりました。
とってもためになる勉強会で、満足しつつ、2次会へ。
うーん。反省ですわ。。かなり気持ち悪い事を言っていたような気が。。。
しまった。
でも楽しかったです。
AIRとしょこたん。
なんか自分のやるべき事が見えた気がしました。
AIRでなんかしないとなあ。
お断り:
タグとかカテゴリーについては、無視して下さい。
10 Jun
最近(というか昨日)、名古屋ちょい絶発表会 vol.2があり、AIRのHTML使ってみましょー、ってなことをやってたのですが、
その後触ってて、ちょっとメモ。
mx:HTMLのid=”browsing”
とすると、
履歴を取るんだったらこんなんでしょうか?
<?xml version=”1.0″ encoding=”utf-8″?>
<mx:WindowedApplication xmlns:mx=”http://www.adobe.com/2006/mxml”; layout=”absolute”>
<mx:Script>
<![CDATA[
import mx.events.FlexEvent;
private function init():void
{
//履歴をtrace()で出力してみる
browsing.addEventListener(Event.LOCATION_CHANGE, function():void{
trace(browsing.location);
});
}
private function changeLoc(e:FlexEvent):void
{
browsing.location = e.target.text;
}
]]>
</mx:Script>
<mx:VBox>
<mx:HBox>
<mx:Button label=”<” click=”browsing.historyBack()” />
<mx:Button label=”>” click=”browsing.historyForward()” />
<mx:Button label=”reload” click=”browsing.reload()” />
<mx:TextInput id=”urls” enter=”changeLoc(event)” />
</mx:HBox>
<mx:HTML id=”browsing” width=”500″ height=”700″ />
</mx:VBox>
</mx:WindowedApplication>
で、僕の経験不足+知識不足なのでしょうけど、ブラウザに履歴を残さずに移動するには、PHPなら、
header(”Location: http://sample.com”
;
とか書いておけばいいってきいたんですけど、AIRで作れば、上の方法で履歴をとれば、headerでも履歴を残せます。
例えば、試しに。
http://www.hi-farm.net/labs/location.php
これは
<?php
header(”Location: http://www.hi-farm.net”
;
?>
ってだけ書いているファイルで、
上にかいたコードを使ってみると、
http://www.hi-farm.net/labs/location.php
http://www.hi-farm.net/
って出力されます!!
これって普通ですか?
2008年2月17日01:01
10 Jun
ちょいと間ができてしまいましたが、AIRをもう一度再勉強!!ってことでいろいろ資料をみていたんですが、こんな機能がありましたね。
flash.system.Shellクラスです。
idleThreshold:int -> これで指定した秒数、マウス操作、キーボード操作しないとEvent.USER_IDLEイベントを送出します。
ってことは!デスクトップアプリとしてはアラームやらなんか面白い事ができそうですね。
僕はちなみに、数秒間何もしなければ恥ずかしい音声を流す、というアプリを作りました。
著作権とかで問題があるので、その辺を改めて作り直したら配布しますね。
使い方は、
<?xml version=”1.0″ encoding=”utf-8″?>
<mx:WindowedApplication xmlns:mx=”http://www.adobe.com/2006/mxml”; layout=”absolute” creationComplete=”initApp()”>
<mx:Script>
<![CDATA[
import flash.system.Shell;
import flash.events.Event;
private function alertSet():void{
//基本設定
// タイムリミットは5秒
Shell.shell.idleThreshold = 5;
//IDLEイベントの設定(何もしなかった場合の設定)
Shell.shell.addEventListener(Event.USER_IDLE, idleHandler);
// IDLE状態を解除された時の設定
Shell.shell.addEventListener(Event.USER_PRESENT, userPresentHandler);
}
private function idleHandler(e:Event):void{
//Idle状態になった場合の挙動
}
private function userPresentHandler(e:Event):void{
//Idle状態でなんらかの操作をした場合の挙動
}
]]>
</mx:Script>
</mx:WindowedApplication>
ただ、僕の場合、idleThresholdを5にすればよかったですが、2だとエラーを吐き出しました。なんででしょう?
2007年11月8日23:37
9 Jun
金曜、土曜と色々と勉強会へ行ってきました。
まず、金曜。
Takeshi MAX Japan 2007 @アップルストア心斎橋
19:00にアップルストアにつくも、人が少なめ。
僕は初めての発表だったので、人が少なめでほっとしていたのですが、イベントが始まり、エグゼクティブたけしの基調講演が行われ、素敵なTakeshi MAXグッズが発表され、進行して行くうちに、人が集まってきたようです。
で、初めての発表。内容はAIR事始め、ってことで、AIRの導入編という内容でした。
初め若干緊張しましたが、なんとかなって良かったです。
nitoyonさんに優しい言葉を頂き、これからも発表とかしたいな、と思いました。
そのnitoyonさんも飛び入りで発表。ほんとにnitoyonさんのプレゼンはすごいなー、おもろいし、とかんしんしてました。
飲み会もやっぱりおもろかったです。
仕事のはなしやらそうでない話しやら、すごく楽しかったです。
次回は11月下旬ころらしいです。日程があえば参加しそうです。
土曜日:
実家で一泊し、お昼には名古屋へ。
WCAN automnへ。
いつも参加しているWCAN mini asチームが発表するという事で、参加しました。
WCAN miniにはちょくちょく参加してたのですが、おっきい方は初めて。
運動会がすごく盛り上がってて、楽しかったです。
後は、miniと違ってASを使っていない人にどういう話し方をすれば上手く伝えられるんだろうか、ということを考えさせられました。
今回のWCANは2セッションで、もう一つは百式の人でした。
内容はもちろんなのですが、僕個人的には、内容の事より、プレゼンの仕方が上手いなー、ってことを見てました。
特に、前半で話していた内容をそのまま後半で実践しているところとか、「やるなぁこの人」とうなってました。
ただ、勉強会の段階でお酒が抜けてなくて、正直普段より上機嫌でした。。
そして懇親会。
いろんな人とあってご挨拶しつつ、ASチームの方や他の方ともお話しする。
AS mini mini会をやろう、と。 是非実現したいっす。
店をかえてもう一件のみに行く。
そこではASチームの人たちと熱く話す。
変態話は変態なのですが、文字通りの変態でした。
ただ、最高に楽しかったです。AIRベータ2だとか、Apolloとか。
やっぱりいろんな人とあっていろんな人と話すのは楽しいですね。
これからもいろんな人と知り合いたい、と思いました。
2007年10月21日01:11
9 Jun
多分、とーっくに知っている方は多いのでしょうが、AOLで、こんなAIRアプリがありました。
AOL Music – top 100 videos BETA
http://music.aol.com/help/syndication/desktop-widgets
早速ダウンロード&インストール。
様はAOLmusicで扱っているミュージックビデオのプレーヤーなんですけど、音楽好きな僕としては、大変うらやましいです。
間違いなくFlexで作ったんだと思いますが、こういうのが作れるのって、コンテンツホルダーと仕事しないと実現って難しそうですよね?
やろうと思えば個人で、ローカルにあるビデオを再生するプレーヤーなんてのは直ぐに作れるとは思うのですが、コンテンツ量が少ないから、いまいち面白みに欠けると思うんですよ。
というか、ローカルの音楽やビデオを再生するだけなら、iTunesでいいやん!って話しになりそうだし。
そう考えると、日本ではYahooとかMTV Japanとかでしょうかね。
今回のtop 100 videosは再生させるのが主な機能な気がしますが、ネットワーク機能を使えばもっといろいろできますよね。
そんな感じのとこ相手にAIRアプリ作れたらおもしろいだろうなーなんて考えたのでした。
でも、、、、現在のAIRアプリは日本語入力があやしいからなあ。。。。
2007年10月15日01:20
9 Jun
AIRもbeta2になり、変更がありました。
主なところは、akihiro kamijoさんのブログにありますが、
http://weblogs.macromedia.com/akamijo/archives/2007/10/adobe_air_2.cfm#more
引用開始———————-
1 ByteArray.infrate()とByteArray.deflate()メソッドがなくなった。
2 ClipboardManagerクラスとTransferableDataクラスがClipboardクラスに置き換えられた。
3 DragManager.isDraggingがメソッドからプロパティに変更
4 Doorクラスが廃止。
5 Fileクラスが変更
File.listDirectories() -> File.getDirectoryListing()
File.listDirectoriesAsync() -> File.getDirectoryListingAsync()
File.listRootDirectories() -> File.getRootDirectories(9
File.relativize() -> File.getRelativePath()
File.resolve() -> File.resolvePath()
6 NativeWindow
visible プロパティがコンストラクタではなく属性として指定するように変更。
Stage.window は Stage.nativeWindow に変更されました。
NativeWindowCapabilties クラスが無くなり、代わりに NativeWindow クラスの属性として実装されました。
7 Systemのpause(), resume(), gc()メソッドがデバッグモードのみ使用可能。
exit()はAIRでは使えなくなり、代わりに、Shell.exit()を使うようにする。
—————引用 終わり
他にもあるようで、変更点は多いですね。
で、僕の場合は、TransferableDataとFileをよく使ってたのですが、やっぱり変更に伴いつまずきました。
TransferableDataは、Clipboardクラスに入ったのですが、入ったはいいが、どうすればデータを取得できるかがわからない。
しかも、困った事に、自分が参照していた言語リファレンスのバージョンがbeta2でなかったため、いつまでたっても答えがみつからないという悲惨な状況でした。
古いバージョンを利用している人は、最新版をここからダウンロードしましょうね。
http://labs.adobe.com/wiki/index.php/AIR:Documentation#Flex_Developers
で、どうやればデータを取得できるかですが、
例えば、ドラッグしたテキストデータを取得する場合なら、
<mx:Script>
<![CDATA[
//---------------drag and drop
import mx.core.*;
import flash.desktop.DragManager;
import flash.events.NativeDragEvent;
import flash.desktop.Clipboard;
import flash.desktop.ClipboardFormats;
import flash.desktop.ClipboardTransferMode;
private var clip:Clipboard;
private function acceptDragDrop():void{
data_la.addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER, dragEnterFromFinder);
data_la.addEventListener(NativeDragEvent.NATIVE_DRAG_DROP, dropFromFinder);
clip = new Clipboard();
}
private function dragEnterFromFinder(e:NativeDragEvent):void{
DragManager.acceptDragDrop(appBox);
}
private function dropFromFinder(e:NativeDragEvent):void{
clip = e.clipboard;
//get text
trace(clip.getData("air:text"));
}
]]>
</mx:Script>
<mx:Label id=”data_la” />
てな感じで取得できました!
NativeDragEventのclipboardのgetData(”air:text”)で取得できる、ということです。
当然、text形式でない場合は、別途変更して下さい。
ああ、airに興味を持った宿命とは思うが、変更が多い。。。
今まで作成していたairアプリがそのままではコンパイルできないという深みにはまっています。。。。
2007年10月12日03:24
9 Jun
Actionscript 3.0 の文字コード検知クラスを作成してみました。
ファイルはここにおいています。
http://www.hi-farm.net/aslib/detect.lzh
このクラスが何をするための物かと言えば、
文字コードを検知するものです。
ファイルをswfに取り込む時に、文字コードをutf-8に変換するものは、URLStreamのreadMultiByteメソッドがあるのですが、例えば、読み込むファイルの文字コードがランダムで指定できない場合、文字コードを検知するのが面倒でした。
そんな面倒なことはやりたくない!ということで、読み込もうとする文字コードの種類を検知するクラスを作成してみました。
簡単に言えば、
URLStreamを使ってファイルを読み込む場合:DetectOnWebクラス
FileStreamを使う場合:DetectOnAirクラス
を使って下さい。
言い直すと、
web上にあるファイルを調べる場合:DetectOnWebクラス
AIRを使ってローカルファイルを調べる場合:DetectOnAirクラス
ということです。
使い方は、
1 インポートする
2 インスタンス作成する
3 リスナー設定する
4 detectCharset(読み込むファイルのURL:String);
5 リスナーで答えを取得
という流れです。
例としてはこんな感じです。
DetectOnAirクラス:
<?xml version=”1.0″ encoding=”utf-8″?>
<mx:WindowedApplication xmlns:mx=”http://www.adobe.com/2006/mxml”; layout=”absolute” creationComplete=”initApp()”>
<mx:Script>
<![CDATA[
import net.hifarm.encode.DetectOnAir;
private var detect:DetectOnAir;
private function initApp():void{
detect = new DetectOnAir();
detect.addEventListener("completeData", comp);
//下のはローカルファイルのURL表現の例です。 detect.detectCharset("file:///Users/mmlemon/Documents/Flex%20Builder%20Moxie/indexInPDF/shift-jis.txt"
;
}
private function comp(e:Event):void{
trace(detect.result);
}
]]>
</mx:Script>
</mx:WindowedApplication>
DetectOnWebクラス:
<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml”; layout=”absolute” creationComplete=”initApp()”>
<mx:Script>
<![CDATA[
import net.hifarm.encode.DetectOnWeb;
private var detect:DetectOnWeb;
private function initApp():void{
detect = new DetectOnWeb();
detect.addEventListener("completeData", comp);
detect.detectCharset("http://blog.hi-farm.net/"
;
}
private function comp(e:Event):void{
trace(detect.result);
}
]]>
</mx:Script>
</mx:Application>
すると、いずれも『detect.result』というところに結果が反映されます。具体的には、
“iso-2022-jp” , “euc-jp” , “utf-8″ , “shift-jis” , “iso-8859-2″
です。ちなみに、エラーが発生した場合、エラーメッセージがdetect.resultに返されます。
iso-8859-2は、iso-2022-jp、euc-jp、utf-8、shift-jisに当てはまらない結果が出た場合に示されます。
注意点:
現在は日本語しか判別できません。
韓国語や中国語の判定はできないのであしからず。
まだ作ったばかりで間もないため、不具合やエラーがあるかもしれません。
その場合、メールいただけると幸いです。
2007年9月26日01:08
9 Jun
MXNAにて、こんなアプリ見つけました。
Analytics Reporting Suite
http://www.aboutnico.be/index.php/google-analytics-air-beta-sign-up/
Google Analyticsを使える状態にある事は、当然前提です。
Ajaxで見せているGoogleの画面も結構いいな、なんて思ってましたが、グラフを切り替えたときに、滑らかなアニメーションでそのグラフの変化を見せられたりして、相当使いやすかったです。
やっぱりAIRっていうか、swfってアプリケーションとしても使い勝手の良い物を作成できるんだ、とおもったのでした。
2007年9月25日15:04