この4月から私もマカーになったので、CoverFlowのインタフェースにも慣れてきた(と、言いつつほとんど仮想マシンのubuntu使っているけど)。また、iPodもCoverFlowなインタフェースを持っているので、ちょっと作ってみるのがいいんじゃない?ということで、簡単にFlexで作ってみた。

ネタは、写真をCoverFlowで表示するというもの。Flex CoverFlowで遊んでみた - l4lを参考にして、作ってみた。なんかsearchResultのループで回すところがなんか納得できなかったので、そこだけは自分で簡単にやってみた。

しかし、元ネタのサンプルFlex CoverFlow performance improvement, Flex Carousel Component, and Vertical CoverFlowを見ると、Carouselの方がイカしているじゃない?というわけでこちらを採用。Carouselという言葉の訳では、回転木馬らしいのだけども、「回転木馬」って言われてもしっくりこないので、とりあえずCoverFlowの亜種と言ったらいいのかしらん。

で、こんな感じ。例によって、写真は、私のホンジュラスのダイビングの成果。

サーバサイドのソースは、こう。単純にディレクトリの中のファイルを適当なXMLで出力しているだけ。

  1. <?php
  2. $dir = 'diving';
  3. $doc = new DomDocument('1.0', 'UTF-8');
  4. $doc->formatOutput = true;
  5.  
  6. $path = 'http://' . $_SERVER['HTTP_HOST'] . '/playgrounds/coverflow';
  7. if (is_dir($dir)) {
  8.     if ($dh = opendir($dir)) {
  9.         $root = $doc->createElement('images');
  10.         $root = $doc->appendChild($root);
  11.         while (($file = readdir($dh)) !== false) {
  12.             if ($file === '..' or $file === '.') {
  13.                 continue;
  14.             }
  15.             $image = $doc->createElement('image', "$path/$dir/$file");
  16.             $root->appendChild($image);
  17.         }
  18.         closedir($dh);
  19.     }
  20. }
  21. echo $doc->saveXML();

そして、Flex側のコードは、こんな感じ。Doug McCuneさんのswcファイルはインクルードしておく。

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
  3.     xmlns:coverflow="com.dougmccune.coverflow.*"
  4.     layout="vertical" horizontalAlign="center" verticalAlign="middle" width="600" height="400"
  5.     xmlns:containers="com.dougmccune.containers.*"
  6.       initialize="searchService.send()">
  7.     <mx:Script>
  8.         <![CDATA[
  9.             import mx.controls.Alert;
  10.             import mx.collections.XMLListCollection;
  11.             [SWF(frameRate="24")]
  12.             import mx.core.Container;
  13.             import mx.events.FlexEvent;
  14.             import mx.controls.Image;
  15.             import mx.rpc.events.ResultEvent
  16.             [Bindable]
  17.             private var serverURL:String = "images.php";
  18.             [Bindable]
  19.             private var xml:XMLListCollection;
  20.             private function getResult(event:ResultEvent):void
  21.             {
  22.                 xml = new XMLListCollection(XML(event.result)..image);
  23.                 coverflow.selectedIndex=int(xml.length/2);
  24.             }
  25.             private function test(event:Event):void
  26.             {
  27.                 mx.controls.Alert.show(event.target.parent.source);
  28.             }
  29.         ]]>
  30.     </mx:Script>
  31.     <mx:HTTPService id="searchService" url="{serverURL}" resultFormat="e4x" result="getResult(event)" />
  32.     <mx:VBox id="box" verticalGap="0" height="100%" width="100%" maxWidth="600" maxHeight="400">
  33.         <containers:CarouselContainer id="coverflow" width="100%" height="100%"
  34.             horizontalGap="10" borderStyle="solid" backgroundColor="0x000000"
  35.             reflectionEnabled="true" autoUpdateFlexMaterials="true">
  36.             <mx:Repeater id="rp" dataProvider="{xml}">
  37.                     <mx:Box name="p{rp.currentItem}" width="300" height="225" horizontalScrollPolicy="off" verticalScrollPolicy="off" paddingTop="20">
  38.                     <mx:Image horizontalAlign="center" name="img{rp.currentItem}"
  39.                          width="250" height="225" useHandCursor="true" buttonMode="true"
  40.                           source="{rp.currentItem}"  click="test(event)" />
  41.                     </mx:Box>
  42.             </mx:Repeater>
  43.         </containers:CarouselContainer>
  44.         </mx:VBox>
  45. </mx:Application>

画像をクリックするとtestという関数を呼び出してalertを出すようにしているのだが、その関数で画像を大きくするとかの処理を書いたら、もう少し使える仕組みになるかな。

うーむ。しかし、いい写真だなぁ。