Flickrで遊ぶ(Illustrator篇)

今日も暑いです。最近クマゼミが朝から鳴くので寝てられません。でも、知ってました?クマゼミってとっても飛翔力低いんですよ。あんまりにうるさい時はベランダから植木に止まっている連中に水かけて退散させたりするんですけど、飛び立ったのは良いけど隣の木までとかどんだけ無精するんでしょう。それも重たそうに飛んでますからねぇ。
捕まえるのも簡単でそ〜っと近づいておもむろにつかむと簡単に捕らえられたりします。食べると美味しいらしいですがなかなかそんな心境まで至らない今日この頃なのです。
毎度まいど役に立たないものばかり作っている訳ですが、今回のはIllustratorからFlickrのAPIをたたいてサムネイルを作ってそこから画像を選んでダウンロード→配置ってのをやってみようと思います。

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:WindowedApplication     xmlns:mx=”http://www.adobe.com/2006/mxml&#8221; xmlns:aral=”*”
    creationComplete=”photoService.send();”>
    <mx:HTTPService id=”photoService” url=”http://api.flickr.com/services/feeds/photos_public.gne&#8221; resultFormat=”e4x”
        result=”photoResultHandler(event);” fault=”photoFaultHandler(event);”>
   </mx:HTTPService>
   
    <mx:Script>
        <![CDATA[
            import flash.net.*;
            import mx.controls.Alert;
            import mx.rpc.events.FaultEvent;
            import mx.rpc.events.ResultEvent;
            import flash.events.*;
            import flash.filesystem.*;
            import com.adobe.csawlib.illustrator.Illustrator;
            import com.adobe.illustrator.*;

            private var app:com.adobe.illustrator.Application = Illustrator.app;
            private var doc:Document = app.documents.add();
            private var txFrame:TextFrame = doc.textFrames.add();

            private var fileName:String;
            private var FileGet:URLLoader;
            [Bindable] private var photoFeed:XML;

            private namespace atom = “http://www.w3.org/2005/Atom&#8221;;
            use namespace atom;

            private function parseImageUrl(fromHtml:XMLList):String
            {
                var pattern:RegExp = /img src=”(.+?)” /;
                var results:Array = pattern.exec(fromHtml);
                var imageURL:String = results[1];
                return imageURL;
            }

            private function photoResultHandler(event:ResultEvent):void
            {
                photoFeed = event.result as XML;
            }

            private function photoFaultHandler(event:FaultEvent):void
            {
                txFrame.contents += “Could not load photo feed\r”;
            }

            private function getCon(evt:MouseEvent):void
            {
                FileGet = new URLLoader();
                FileGet.dataFormat = URLLoaderDataFormat.BINARY;
                FileGet.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
                FileGet.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
                FileGet.addEventListener(Event.COMPLETE, onComplete);
                txFrame.contents = String(evt.currentTarget.source) + ” Download Start.\r”;
                var pattern:RegExp = /http:\/\/.+\/.+\/(.+\..+)/;
                var fNm:Array = pattern.exec(evt.currentTarget.source);
                fileName = fNm[1].replace(“m.”,”b.”);
                var tgtadd:String = String(evt.currentTarget.source).replace(“m.”,”b.”);
                txFrame.contents = tgtadd + ” Download Start.\r”;
                var request:URLRequest = new URLRequest(tgtadd);
                FileGet.load(request);
            }

            private function onIOError(evt:IOErrorEvent):void
            {
                txFrame.contents += “There was an IO Error.\r”;
                txFrame.contents += “Could not place Image.\r”;
            }

            private function onSecurityError(evt:Event):void
            {
                txFrame.contents += “There was a security error.\r”;
            }

            private function onComplete(evt:Event):void
            {
                txFrame.contents += “File was successfully downloaded.\r”;
                txFrame.contents += “SIZE=” + FileGet.bytesTotal + “\r”;
                var desktop_file : File = File.desktopDirectory;
                var file : File = desktop_file.resolvePath(fileName);
                var stream:FileStream = new FileStream();
                try
                {
                    stream.open(file,FileMode.WRITE);
                    stream.writeBytes(FileGet.data);
                    var getFileNm:String = file.nativePath;
                    txFrame.contents += getFileNm + ” Output Successful.\r”;
  &nb
sp;             }
                catch(error:IOError)
                {
                    txFrame.contents += “File Output Error.\r”;
                }
                finally
                {
                    stream.close();
                    var obj:PlacedItem = doc.placedItems.add();
                    obj.file = file;
                    obj.height = obj.height*0.5;
                    obj.width = obj.width*0.5;
                    obj.left = 50;
                    obj.top = 200 + obj.height;
                }
            }
        ]]>
    </mx:Script>

    <mx:Fade id=”fadeIn” duration=”1500″ alphaFrom=”0″ alphaTo=”1″/>
    <mx:Fade id=”fadeOut” duration=”1500″ alphaFrom=”1″ alphaTo=”0″/>
    <mx:VBox height=”100%” width=”100%” verticalAlign=”top” horizontalAlign=”right”>
        <mx:Button id=”monButton” label=”refresh” click=”photoService.send();”/>
        <mx:Tile width=”100%” height=”100%”>
            <mx:Repeater id=”photos” dataProvider=”{photoFeed.entry}”>
                <mx:Box
                    xmlns:mx=”http://www.adobe.com/2006/mxml&#8221;
                    textAlign=”center”>
                    <mx:Image id=”myImage” source=”{parseImageUrl(photos.currentItem.content)}”
                        completeEffect=”{fadeIn}” scaleX=”0.3″ scaleY=”0.3″ click=”getCon(event);”/>
                </mx:Box>   
            </mx:Repeater>
        </mx:Tile>
        <mx:ControlBar horizontalAlign=”center”>
        </mx:ControlBar>
    </mx:VBox>
</mx:WindowedApplication>

今回の流れは
flickrからatomを取得→イメージのURLを抽出→サムネイルを生成→クリックでダウンロード開始→ダウンロードしたファイルを配置
となります。
前にwebからイメージを取得したのはURLLoaderでしたが今回は「mx:HTTPService」コンポーネントを利用します。

<mx:WindowedApplication     xmlns:mx=”http://www.adobe.com/2006/mxml&#8221; xmlns:aral=”*”
    creationComplete=”photoService.send();”>
    <mx:HTTPService id=”photoService” url=”http://api.flickr.com/services/feeds/photos_public.gne&#8221; resultFormat=”e4x”
        result=”photoResultHandler(event);” fault=”photoFaultHandler(event);”>
    </mx:HTTPService>

アクセスに必要な設定はコンポーネント内に記述しておきます。
HTTPリクエストの送出はsend()メソッドで行います。この例ではWindowedAppricationが読み込まれた場合とrefreshボタンがクリックされた場合にリクエストが送出されます。

コードの要点です。

            private var app:com.adobe.illustrator.Application = Illustrator.app;
            private var doc:Document = app.documents.add();
            private var txFrame:TextFrame = doc.textFrames.add();

この部分はIllustratorに対して新規書類を生成し、textFrameを追加する部分です。

            private var fileName:String;
            private var FileGet:URLLoader;
            [Bindable] private var photoFeed:XML;

幾つかの変数がprivateで定義されています。photoFeedは[Bindable]であることに注意。

            private namespace atom = “http://www.w3.org/2005/Atom&#8221;;
            use namespace atom;

取得するフィードはatomですのでネームスペースを上記のように設定しておきます。
HTTPService通信が正常に完了したときと失敗したときに、それぞれresultイベントとfaultイベントが送出されます。ですから対応したリスナの設定が必要となります。「mx:HTTPService」のresultEventの処理を見てみましょう。

            private function photoResultHandler(event:ResultEvent):void
            {
                photoFeed = event.result as XML;
            }

「mx:HTTPService」コンポーネント上でresultFormat=”e4x”と返り値をECMAScript for XMLにて取得する様に指定しています。ですからここでもXML形式を受け取る事を明示しておきましょう。こうしておけば

photoFeed.entry

の様に要素名をドットでつないだ形でのアクセスが可能となります。
初期に呼び出されるコードは以上です。atomが取得できましたので。サムネイルを生成します。

        <mx:Repeater id=”photos” dataProvider=”{photoFeed.entry}”>
                <mx:Box
                    xmlns:mx=”http://www.adobe.com/2006/mxml&#8221;
                    textAlign=”center”>
                    <mx:Image id=”myImage” source=”{parseImageUrl(photos.currentItem.content)}”
                        completeEffect=”{fadeIn}” scaleX=”0.3″ scaleY=”0.3″ click=”getCon(event);”/>
                </mx:Box>    
            </mx:Repeater>

繰り返し要素を処理するにはrepeaterを利用します。repeaterがバインドするdataProviderはphotoFeedのentry要素です。
実際の配置はmx:Imageコンポーネントがsourceを取得して行います。
同時にclickもハンドルしておきます。これは後ほどクリックを検出して配置処理を行う為です。

            private function parseImageUrl(fromHtml:XMLList):String
            {
                var pattern:RegExp = /img src=”(.+?)” /;
                var results:Array = pattern.exec(fromHtml);
                var imageURL:String = results[1];
                return imageURL;
            }

こちらがsourceに対応するファンクションです。entry以下のcontentからimgタグの引数を抽出して返します。
repeaterはdataProviderのentryの数だけ反復します。今回の例では20個ありますからrepeaterItemは20個になります。
以下、配置処理になる訳ですが、以前のWebからの処理とほぼ変わりませんので解説は割愛します。

最後に[Bindable]の説明を。ある変数をbindableとして定義し利用すると、その変数を動的に変更した場合でもbind先が自動的に変更を検出し新しいデータを利用して処理してくれる仕組みです。
今回の場合はatomをrefreshすると自動的にrepeaterが新しいデータを処理します。

実行イメージ

flickr_thumb.png

flickr.zxp
サンプルエクステンションも置いておきますね。
広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google フォト

Google アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中