WonderflのWebイベント「JAM HTML5 Flash」のsession2「MediaRSSをフィードとするフォトビューアをつくってください」に参加(投稿)してみました。
お題は「MediaRSSに準拠したフィードを読み込み、いかに画像を魅力的に見せるかを競って頂きます」というもので、今日、子供と遊びながら「画像を魅力的にみせるには・・・」と考えてみたのですが、良いアイデアは浮かばず、結局、ありがちですがPapervision3dをつかったフォトビュアーを作ってみました。
全画面版を実行
左上のテキストボックスに検索語を入れてリターンキーを押すと、FlickrからRSSフィードを取得して、サムネイルを表示し、サムネイルをクリックすると画像が拡大表示されます。
package practice { import flash.display.BitmapData; import flash.display.Loader; import flash.display.MovieClip; import flash.events.KeyboardEvent; import flash.net.URLLoader; import flash.net.URLRequest; import flash.events.MouseEvent; import flash.system.LoaderContext; import flash.text.TextField; import flash.text.TextFieldType; import flash.text.TextFormat; import flash.display.StageAlign; import flash.display.StageQuality; import flash.display.StageScaleMode; import flash.events.Event; import org.papervision3d.core.geom.renderables.Triangle3D; import org.papervision3d.core.geom.renderables.Vertex3D; import org.papervision3d.core.geom.TriangleMesh3D; import org.papervision3d.core.math.NumberUV; import org.papervision3d.events.InteractiveScene3DEvent; import org.papervision3d.materials.BitmapMaterial; import org.papervision3d.materials.ColorMaterial; import org.papervision3d.materials.special.CompositeMaterial; import org.papervision3d.materials.utils.MaterialsList; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.primitives.Plane; import org.papervision3d.core.effects.view.ReflectionView; [SWF(width = "440", height = "440", backgroundColor = "0x000000", fps = "60")] public class Practice95 extends ReflectionView { private var _feed:String = "http://api.flickr.com/services/feeds/photos_public.gne?tags="; private var media:Namespace = new Namespace("http://search.yahoo.com/mrss/"); private var text:TextField; private var list:Vector.= new Vector. (); private var map:Array; private var mes:Array; private var counter:int = 0; private var isSelected:Boolean = false; private var frame:Frame = null; private var pop:TextField; public function Practice95():void { stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; stage.quality = StageQuality.MEDIUM; this.viewport.interactive = true; initText(); initObj(); } private function initText():void { text = new TextField(); text.x = 5, text.y = 5; text.type = TextFieldType.INPUT; text.restrict = null; text.width = 100; text.height = 20; text.border = true; text.text = "kamakura"; text.background = true; text.backgroundColor = 0xffffff; text.borderColor = 0xcccccc; text.border = true; text.addEventListener(KeyboardEvent.KEY_UP, onKeyUp); addChild(text); pop = new TextField(); pop.restrict = null; pop.border = true; pop.multiline = true; var tx:TextFormat = new TextFormat(); tx.size = 12; pop.defaultTextFormat = tx; pop.background = true; pop.backgroundColor = 0xffffff; pop.borderColor = 0xcccccc; pop.border = true; pop.alpha = 0.5; } private function initObj():void { camera.focus = 500; camera.zoom = 2; camera.z = -1600; var col:ColorMaterial = new ColorMaterial(0xffffff, 0.5); var co:CompositeMaterial = new CompositeMaterial(); co.addMaterial(col); var floor:Plane = new Plane(co, 5000, 5000, 12, 12); scene.addChild(floor); floor.pitch( -90); var cm:ColorMaterial = new ColorMaterial(0x0099CC); cm.doubleSided = true; addEventListener(Event.ENTER_FRAME, update); serch(text.text); } private function onKeyUp(e:KeyboardEvent):void { if (e.keyCode == 13) { serch(e.currentTarget.text); } } private function update(e:Event):void { if (!isSelected) { camera.x += (mouseX / stage.stageWidth * 600 - 300) - camera.x * 0.07; camera.y += (mouseY / stage.stageHeight * 200) - camera.y * 0.07; for (var i:int = 0; i < list.length; i++) { var p:Plate = list.shift(); p.update(); if (p.live) { list.push(p); }else { scene.removeChild(p); } } singleRender(); }else if(frame!=null){ frame.update(); } } private function serch(word:String):void { counter = 0; map = new Array(); mes = new Array(); for (var i:int = 0; i < list.length; i++) { list[i].remove(); } var url:String = _feed+encodeURIComponent(word)+"&format=rss_200"; var ldr:URLLoader = new URLLoader(); ldr.addEventListener(Event.COMPLETE, function _load(e:Event):void { ldr.removeEventListener(Event.COMPLETE, _load); onImageLoaded(XML(ldr.data)..media::thumbnail.@url.toXMLString().split('\n'), XML(ldr.data)..media::content.@url.toXMLString().split('\n'), XML(ldr.data)..media::description.text().toXMLString().split('\n')); }); ldr.load(new URLRequest(url)); } private function onImageLoaded($images:Array, $url:Array, $desc:Array):void { var ldr:Loader; for (var i:int = 0; i < $images.length; ++i) { map[$images[i]] = $url[i]; mes[$images[i]] = $desc[i]; ldr = new Loader(); ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoadPhotoCompleted); ldr.load(new URLRequest($images[i]), new LoaderContext(true)); } } private function imageLoadPhotoCompleted(e:Event):void { var i:int = counter++; var loader:Loader = e.target.loader; var bmp:BitmapData = new BitmapData(loader.width, loader.height); bmp.draw(loader); var bm:BitmapMaterial = new BitmapMaterial(bmp); bm.oneSide = false; bm.interactive = true; var p:Plate = new Plate(bm, 300, 300, 2, 2, map[e.target.url],mes[e.target.url]); p.bx = (i % 5) * 500-1250; p.bz = Math.floor(i / 5) * 500-1000; p.by = 200; p.x = 10000; p.z = 10000; p.roll(0); p.addEventListener(InteractiveScene3DEvent.OBJECT_PRESS, onPress); p.addEventListener(InteractiveScene3DEvent.OBJECT_OVER, onOver); p.addEventListener(InteractiveScene3DEvent.OBJECT_OUT,onOut); list.push(p); scene.addChild(p); } private function onPress(e:InteractiveScene3DEvent):void { if (!isSelected) { isSelected = true; var p:Plate = e.displayObject3D as Plate; frame = new Frame(p.url); addChild(frame); frame.addEventListener(MouseEvent.MOUSE_DOWN, onFramePress); } } private function onOver(e:InteractiveScene3DEvent):void { var p:Plate = e.displayObject3D as Plate; pop.text = p.mes; pop.x = mouseX - 50; pop.y = mouseY - 25; pop.width = pop.textWidth + 10; pop.height = pop.textHeight + 5; addChild(pop); } private function onOut(e:InteractiveScene3DEvent):void { removeChild(pop); } private function onFramePress(e:Event):void { removeChild(frame); frame = null; isSelected = false; } } } import flash.display.Loader; import flash.display.MovieClip; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.net.URLRequest; import flash.system.LoaderContext; import org.papervision3d.core.proto.MaterialObject3D; import org.papervision3d.objects.primitives.Plane; class Plate extends Plane { public var bx:Number; public var by:Number; public var bz:Number; private var isRemove:Boolean = false; public var live:Boolean = true; public var url:String; public var mes:String=""; public function Plate(material:MaterialObject3D = null, width:Number = 0, height:Number = 0, segmentsW:Number = 0, segmentsH:Number = 0,u:String=null,ms:String=null) { super(material, width, height, segmentsW, segmentsH); url = u; if(ms!=null)mes = ms.replace("<p>", "").replace("</p>", ""); } public function update():void { if (Math.abs(bx - x) > 1e-8) x += (bx - x) * 0.1; if (Math.abs(by - y) > 1e-8) y += (by - y) * 0.1; if (Math.abs(bz - z) > 1e-8) z += (bz - z) * 0.1; if (isRemove&&(Math.abs(bx + bz - x - z) < 1)) { live = false; } } public function remove():void { bx = -5000; bz = -5000; isRemove = true; } } class Frame extends MovieClip { private var back:MovieClip; private var wait:Wait; private var container:Sprite; private var count:int = 0; public function Frame(url:String) { super(); back = new MovieClip(); addChild(back); wait = new Wait(); addChild(wait); container = new Sprite(); var ldr:Loader = new Loader(); ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoadPhotoCompleted); ldr.load(new URLRequest(url), new LoaderContext(true)); addChild(container); } public function update():void { if (count++ > 20) return; back.graphics.beginFill(0xffffff, 0.1); back.graphics.drawRect(0, 0, parent.width, parent.height); back.graphics.endFill(); } private function imageLoadPhotoCompleted(e:Event):void { var ldr:Loader = e.target.loader; var rate:Number = parent.width / ldr.width; rate = Math.min(rate, parent.height / ldr.height) * 0.95; if (rate < 1.0) { container.scaleX = rate; container.scaleY = rate; container.x = (parent.width - ldr.width * rate)/2.0; container.y = (parent.height - ldr.height* rate)/2.0; }else { container.x = (parent.width - ldr.width)/2.0; container.y = (parent.height - ldr.height)/2.0; } container.addChild(ldr); wait.removeEvt(); removeChild(wait); } } class Wait extends MovieClip { private var list:Array; private var step:Number = 15; private var radius:Number = 20; private var centerX:Number; private var centerY:Number; private var counter:int; public function Wait() { list = new Array(); var angle:Number = 0; while (angle < 365) { var ani:Ani = new Ani(); ani.deg = angle / 180 * Math.PI; ani.radius = 5; list.push(ani); angle += step; } centerX = 240; centerY = 240; addEventListener(Event.ENTER_FRAME, update); } public function removeEvt():void { removeEventListener(Event.ENTER_FRAME, update); } private function update(e:Event):void { centerX = parent.parent.width / 2; centerY = parent.parent.height / 2; graphics.clear(); for (var i:int = 0; i < list.length; i++) { var px:Number = radius * Math.cos(list[i].deg)+centerX; var py:Number = radius * Math.sin(list[i].deg)+centerY; var alpha:Number = (list.length - i) / list.length; graphics.beginFill(0xaaaaaa,alpha); graphics.drawCircle(px, py, radius/10); graphics.endFill(); } graphics.lineStyle(8, 0xaaaaaa); graphics.moveTo(centerX, centerY); graphics.lineTo(radius * Math.cos(list[10].deg)+centerX, radius * Math.sin(list[10].deg)+centerY); list.push(list.shift()); } } class Ani { public var deg:Number; public var radius:Number; }