Twitterの検索z軸つき

wonderfl本のイベント用に作った没ネタ。書籍に掲載したTwitterの検索をz軸で並べると楽しいかもね、というデモ。

▼Wonderfl

▼ActionScript AS3(FP10)
[sourcecode language=”as3″]
/*
* Twitter Search API Method: search
* http://apiwiki.twitter.com/Twitter-Search-API-Method%3A-search
*
* Twitter API 仕様書 (勝手に日本語訳シリーズ)
* http://watcher.moe-nifty.com/memo/2007/04/twitter_api.html
* */
package {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.events.TextEvent;
import flash.filters.DropShadowFilter;
import flash.geom.PerspectiveProjection;
import flash.geom.Point;
import flash.net.URLRequest;
import flash.net.URLLoader;
import flash.text.TextField;
import flash.text.TextFieldType;
import flash.net.navigateToURL;
import flash.display.DisplayObjectContainer;
import flash.geom.Vector3D;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.tweens.ITween;
import org.libspark.betweenas3.easing.*;
/**
* …
* @author umhr
*/
//[SWF(backgroundColor="0x000000",width=465,height=465)]
public class Main extends Sprite {
private var _resultStage:Sprite = new Sprite();
public function Main():void {
//ヘッダーのサーチエリア
//背景
var titleArea:Shape = new Shape();
titleArea.graphics.beginFill(0x39CCFF);
titleArea.graphics.drawRect(0, 0, 465, 23);
addChild(titleArea);
//Serchの文字
var serchWord:TextField = new TextField();
serchWord.text = "Serch:";
serchWord.width = 33;
serchWord.height = 18;
serchWord.x = 2;
serchWord.y = 2;
serchWord.textColor = 0xFFFFFF;
addChild(serchWord);
//テキスト入力欄。キーボードのキーを押し上げた際にonKeyUpが実行される
var title:TextField = new TextField();
title.text = "アップル";
title.width = 426;
title.height = 18;
title.x = 36;
title.y = 2;
title.border = true;
title.borderColor = 0xFFFFFF;
title.background = true;
title.backgroundColor = 0x99DDFF;
title.type = TextFieldType.INPUT;
title.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
addChild(title);

//検索結果を配置するSpriteをaddChild
_resultStage.y = 25;
//_resultStage.z = 0;
addChild(_resultStage);

//初期状態で検索結果画面が出るように、検索を実行する。
serch(title.text);
}

private function onKeyUp(e:KeyboardEvent):void {
//Enterキーのキーコード13だったら、serchメソッドを実行。引数には適すと入力欄の文字列
if (e.keyCode == 13) {
serch(e.currentTarget.text)
}
}

public function serch(serchWord:String):void {
//検索APIにリクエストを投げる
//http://search.twitter.com/crossdomain.xml上で許可をしているので
//特に指定しなくても自動的に確認して、許可を得られる
var myURLLoader:URLLoader = new URLLoader();
myURLLoader.addEventListener(Event.COMPLETE, onCompleteXML);
myURLLoader.addEventListener(IOErrorEvent.IO_ERROR, onIoError);
var xmlURL:String = "http://search.twitter.com/search.atom?q=";
//encodeURIComponent()を使うことによって、#や日本語にも対応
xmlURL += encodeURIComponent(serchWord); //*1
myURLLoader.load(new URLRequest(xmlURL));
}

public function onIoError(e:IOErrorEvent):void {
trace(e.type);
}

private function onCompleteXML(e:Event):void {
//eventListenerを削除
e.currentTarget.removeEventListener(Event.COMPLETE, onCompleteXML);
//_resultStage上のオブジェクトを全て削除
while (_resultStage.numChildren) {
_resultStage.removeChildAt(0);
_resultStage.z = 0;
}

//XML型にキャスト
var myXML:XML = new XML(e.currentTarget.data);
//namespaceを設定
default xml namespace = new Namespace("http://www.w3.org/2005/Atom"); //*2

//要素を取り出して、textFieldを作りならべる
var itemLength:int = myXML.entry.length();
//trace(itemLength)
for (var i:int = 0; i < itemLength; i++) {
//xmlからlink,authorName,titleの各値を取得
var link:String = myXML.entry[i].link[0].@href;
var authorName:String = myXML.entry[i].author.name;
var title:String = myXML.entry[i].title;
//アイコン画像のURLを取得
var imgURL:String = myXML.entry[i].link[1].@href;
//bmpフォーマットのアイコン画像を使っている人も少なくないため、Flashで使えるファイルの拡張子かどうかを判別
var extention:String = imgURL.substr( -4);
extention = extention.toLowerCase();
if (extention != ".jpg" && extention != ".gif" && extention != ".png") {
//Flashで使える画像の拡張子ではなかった場合にはデフォルトアイコンを指定
imgURL = "http://s.twimg.com/a/1254440757/images/default_profile_mini.png";
}
//画像のファイル名が日本語などの規定外の文字である場合を考慮しエンコードする
imgURL = encodeURI(imgURL); //*3
//小さい画像で十分なので、名前を差し替える
//imgURL = imgURL.replace(/_normal\./, "_mini\.");

//得られた各値をhtmlTextに入るように整形
var htmldata:String = "";
//htmldata = "<a href=’" + link + "’ target=’_blank’>";
htmldata += "<img src=’" + imgURL + "’ width=’48’ height=’48’ checkPolicyFile=’true’ />";
htmldata += "<b>" + authorName + "</b> " + title + "";

//検索結果のテキストフィールド
var myTextField:TextField = new TextField();
myTextField.width = 300;
myTextField.x = 2+80;
myTextField.wordWrap = true;
myTextField.background = true;
myTextField.backgroundColor = 0x222222;
myTextField.border = true;
myTextField.selectable = false;
myTextField.borderColor = 0x000000;
myTextField.textColor = 0xFFFFFF;
myTextField.htmlText = htmldata;
myTextField.autoSize = "left";
//テキストフィールドのy座標はtfYに加算していくことにより、決定
myTextField.y = 280;
myTextField.z = 3000 – i * 250 + 20;
myTextField.name = String(3000 – i * 250);
myTextField.filters = [new DropShadowFilter(2,90,0×666666,1,8,8)];
_resultStage.addChild(myTextField);
}
_resultStage.addEventListener(MouseEvent.CLICK, onClick);
this.transform.perspectiveProjection = new PerspectiveProjection();
this.transform.perspectiveProjection.projectionCenter = new Point(stage.stageWidth / 2, stage.stageHeight / 2.5);
}
private var _t:ITween;
private function onClick(event:MouseEvent):void {
if (_t != null) {
_t.stop();
}
_t = BetweenAS3.tween(_resultStage, { z: -Number(event.target.name) }, null, 1, Quint.easeOut);
_t.onUpdate = onUpdate;
_t.play();
}
private function onUpdate():void {
var n:int = _resultStage.numChildren;
for (var i:int = 0; i < n; i++) {
_resultStage.getChildAt(i).visible = (_resultStage.getChildAt(i).z+_resultStage.z > -250);
}
}
}
}
[/sourcecode]