In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

mozaic RSS reader

画像の一覧性と、文字の説明的な性質を混交させてみました。
画像にマウスオーバーすることで記事の内容がちらちら垣間見られます。
Get Adobe Flash player
by B44CCD21 02 Dec 2010
/**
 * Copyright B44CCD21 ( http://wonderfl.net/user/B44CCD21 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/9l7Z
 */

// forked from Event's CBC NET
//RSSの記事の文字で画像をトレースしています。放っておくと自動でスクロールします。
//重めです。

package{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.utils.Dictionary;
	import flash.utils.Timer;
	
	[SWF(width = "465", height = "465", frameRate = "15", backgroundColor = "#EEEEEE")]
	
	public class RSSReader extends Sprite{
		private static const XML_PATH:String="http://assets.wonderfl.net/static/assets/session5/cbcnet_feed.xml";
		//private static const LOGO_PATH:String="http://jsrun.it/static/assets/session5/cbcnet_logo.gif"
		public static const _PIXEL_SIZE:int=16;
		public static const _TEXT_FORMAT:TextFormat=new TextFormat(null,PIXEL_SIZE);
		private static const SCROLL_INTERVAL:int=5000;
		
		private static var charDictionary:Dictionary=new Dictionary();
		private var urlLoader:URLLoader;
		private var rss:XML;
		private static var rss_items:Array=new Array();
		private static var index:int=15;
		private var timer:Timer;
		
		public function RSSReader(){
			stage.align=StageAlign.TOP_LEFT;
			stage.scaleMode=StageScaleMode.NO_SCALE;
			
			urlLoader=new URLLoader();
			urlLoader.addEventListener(Event.COMPLETE,rssLoadCompleteHandler);
			urlLoader.load(new URLRequest(XML_PATH));
		}
		
		private function rssLoadCompleteHandler(event:Event):void{
			urlLoader.removeEventListener(Event.COMPLETE,rssLoadCompleteHandler);
			
			rss=XML(XML(urlLoader.data)["channel"]);
			
			timer=new Timer(SCROLL_INTERVAL,0);
			timer.addEventListener(TimerEvent.TIMER,function onTimerTickEvent(event:TimerEvent):void{
				scrollItems("down");
			});
			timer.start();
			stage.addEventListener(MouseEvent.MOUSE_MOVE,function onMouseMoveHandler(event:MouseEvent):void{
				timer.reset();
				timer.start();
			});
			
			scrollItems("down");
		}
		
		private function addRSSItem(direction:String):void{
			var rssItem:RSSItem=new RSSItem(rss["item"][index],null,direction);
			addChild(rssItem);
			
			if(direction=="up"){
				rss_items.unshift(rssItem)
				index=(index>0)?index-1:rss["item"].length()-1;
			}else{
				rss_items.push(rssItem);
				index=(index<(rss["item"].length()-1))?index+1:0;
			}
		}
		
		public function scrollItems(direction:String):void{
			timer.reset();
			timer.start();
			
			for each(var item:RSSItem in rss_items){
				item.scroll(direction);
			}
			if(rss_items.length>=3){
				if(direction=="up"){
					rss_items.pop();
				}else{
					rss_items.shift();
				}
			}
			addRSSItem(direction);
		}
		
	 	public static function createCharArray(str:String):Array{
			var charArray:Array=new Array();
			var tmp_dic:Dictionary=new Dictionary();
			for(var i:Number=0;i<str.length;i++){
				var c:String=str.charAt(i);
				if(charDictionary.hasOwnProperty(c.charCodeAt())){
					if(!tmp_dic.hasOwnProperty(c.charCodeAt())){
						tmp_dic[c.charCodeAt()]=true;
						charArray.push(charDictionary[c.charCodeAt()]);
					}
					continue;
				}
				
				var tf:TextField=new TextField();
				tf.defaultTextFormat=_TEXT_FORMAT;
				tf.selectable=false;
				tf.text=c;
				if(tf.textWidth<=0||tf.textHeight<=0){continue;}
				tf.width=tf.textWidth+4;
				tf.height=tf.textHeight+4;
				
				var text_bmd:BitmapData=new BitmapData(tf.textWidth,tf.textHeight,false);
				text_bmd.draw(tf);
				
				var char_data:Object=new Object();
				char_data["string"]=c;
				char_data["brightness"]=calBrightness(text_bmd);
				char_data["bitmapData"]=text_bmd;
				
				charDictionary[c.charCodeAt()]=char_data;
				charArray.push(char_data);
			}
			charArray.sortOn("brightness");
			return charArray;
		}
		
		private static function calBrightness(src_bmd:BitmapData):Number{
			var b:Number=0;
			for (var x:int=0;x<src_bmd.width;x++){
				for (var y:int=0;y<src_bmd.height;y++){
					var c:int=src_bmd.getPixel(x,y);
					b+=(((c>>16)&255)+((c>>8)&255)+(c&255))/3;
				}
			}
			b/=(src_bmd.width*src_bmd.height);
			return b;
		}
		
		public static function get PIXEL_SIZE():int{
			return _PIXEL_SIZE;
		}
		
		public static function get TEXT_FORMAT():TextFormat{
			return _TEXT_FORMAT;
		}
	}
}

import gs    .TweenLite;

import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.ColorMatrixFilter;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import flash.net.URLRequest;
import flash.net.navigateToURL;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.utils.Dictionary;

import org.osmf.events.TimeEvent;

internal class RSSItem extends Sprite{
	private var item:XML;
	private var charArray:Array;
	
	private var loader:Loader;
	private var text_sp:Sprite;
	private var char_sp_array:Array;
	private var loader_mask_sp:Sprite;
	private var title_tf:TextField;
	private var description_tf:TextField;
	
	private var image_width:int;
	private var image_height:int;
	
	private var direction:String;
	private var position:String;
	
	private static const IMAGE_SCALE:Number=0.5;
	private static const PIXEL_SIZE:int=RSSReader.PIXEL_SIZE;
	private static const IMAGE_EDGE_WIDTH:Number=12;
	private static const HIT_RANGE:Number=8;
	private static const HIT_RANGE_SQUARE:Number=Math.pow(HIT_RANGE,2);
	private static const TEXT_MAGNIFICATION:Number=12.0;
	private static const FILTER_A:Number=1-2/3;
	private static const FILTER_B:Number=1/3;
	private static const GRAYSCALE_FILTER:ColorMatrixFilter=new ColorMatrixFilter(
		[FILTER_A,FILTER_B,FILTER_B,0,0,
			FILTER_B,FILTER_A,FILTER_B,0,0,
			FILTER_B,FILTER_B,FILTER_A,0,0,
			0,0,0,1,0]);
	
	public function RSSItem(item:XML,position:String,direction:String){
		this.item=item;
		this.position=position;
		this.direction=direction;
		var str:String=item["title"]+item["description"];
		
		charArray=RSSReader.createCharArray(str);
		
		loader=new Loader();
		loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onImageLoadCompleteHandler);
		loader.load(new URLRequest(item["image"].toString()));
	}
	
	private function destroy():void{
		parent.removeChild(this);
	}
	
	private function onImageLoadCompleteHandler(event:Event):void{
		loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,onImageLoadCompleteHandler);
		
		var reduced_bmd:BitmapData=createReducedBitmapData(loader);
		image_width=reduced_bmd.width*PIXEL_SIZE;
		image_height=reduced_bmd.height*PIXEL_SIZE;
		
		graphics.beginFill(0xFFFFFF);
		graphics.drawRect(IMAGE_EDGE_WIDTH,IMAGE_EDGE_WIDTH,image_width*IMAGE_SCALE,image_height*IMAGE_SCALE);
		graphics.endFill();
		
		var frame_sp:Sprite=new Sprite();
		frame_sp.graphics.beginFill(0x000000);
		frame_sp.graphics.drawRect(IMAGE_EDGE_WIDTH,0,image_width*IMAGE_SCALE,IMAGE_EDGE_WIDTH);
		frame_sp.graphics.drawRect(0,0,IMAGE_EDGE_WIDTH,image_height*IMAGE_SCALE+IMAGE_EDGE_WIDTH*2);
		frame_sp.graphics.drawRect(IMAGE_EDGE_WIDTH,image_height*IMAGE_SCALE+IMAGE_EDGE_WIDTH,image_width*IMAGE_SCALE,IMAGE_EDGE_WIDTH);
		frame_sp.graphics.drawRect(image_width*IMAGE_SCALE+IMAGE_EDGE_WIDTH,0,IMAGE_EDGE_WIDTH,image_height*IMAGE_SCALE+IMAGE_EDGE_WIDTH*2);
		frame_sp.graphics.endFill();
		
		loader.x=loader.y=IMAGE_EDGE_WIDTH;
		loader.scaleX=loader.scaleY=IMAGE_SCALE;
		
		loader_mask_sp=new Sprite();
		loader_mask_sp.cacheAsBitmap=true;
		loader.cacheAsBitmap=true;
		loader.mask=loader_mask_sp;
		
		text_sp=createTextSprite(reduced_bmd,charArray);
		text_sp.scaleX=text_sp.scaleY=IMAGE_SCALE;
		text_sp.x=IMAGE_EDGE_WIDTH;
		text_sp.y=IMAGE_EDGE_WIDTH;
		
		addChild(loader);
		addChild(frame_sp);
		addChild(loader_mask_sp);
		addChild(text_sp);
		
		x=(stage.stageWidth-width)/2;
		buttonMode=true;
		mouseChildren=false;
		
		scroll(direction);
	}
	
	public function scroll(direction:String):void{
		var i:int;
		if(direction=="up"){
			if(position==null){
				addEventListener(MouseEvent.CLICK,onBottomImageClickHandler);
				y=stage.stageHeight;
				TweenLite.to(this,0.4,{y:stage.stageHeight-20});
				position="bottom"
			}else if(position=="bottom"){
				if(hasEventListener(MouseEvent.CLICK)){
					removeEventListener(MouseEvent.CLICK,onBottomImageClickHandler);
				}
				addEventListener(MouseEvent.CLICK,onCenterImageClickHandler);
				TweenLite.to(this,1.2,{y:(stage.stageHeight-height)/2});
				for(i=0;i<text_sp.numChildren;i++){
					text_sp.getChildAt(i).addEventListener(Event.ENTER_FRAME,onCharSpriteEnterFrameHandler);
				}
				position="center"
			}else if(position=="center"){
				if(hasEventListener(MouseEvent.CLICK)){
					removeEventListener(MouseEvent.CLICK,onCenterImageClickHandler);
					removeEventListener(MouseEvent.CLICK,onLoaderClickHandler);
				}
				addEventListener(MouseEvent.CLICK,onTopImageClickHandler);
				TweenLite.to(this,1.2,{y:-height+20});
				for(i=0;i<text_sp.numChildren;i++){
					text_sp.getChildAt(i).removeEventListener(Event.ENTER_FRAME,onCharSpriteEnterFrameHandler);
				}
				position="top"
			}else{
				if(hasEventListener(MouseEvent.CLICK)){
					removeEventListener(MouseEvent.CLICK,onTopImageClickHandler);
				}
				TweenLite.to(this,1.2,{y:-height,onComplete:destroy});
			}
		}else if(direction=="down"){
			if(position==null){
				addEventListener(MouseEvent.CLICK,onTopImageClickHandler);
				y=-height;
				TweenLite.to(this,0.4,{y:-height+20});
				position="top"
			}else if(position=="top"){
				if(hasEventListener(MouseEvent.CLICK)){
					removeEventListener(MouseEvent.CLICK,onTopImageClickHandler);
				}
				addEventListener(MouseEvent.CLICK,onCenterImageClickHandler);
				TweenLite.to(this,1.2,{y:(stage.stageHeight-height)/2});
				for(i=0;i<text_sp.numChildren;i++){
					text_sp.getChildAt(i).addEventListener(Event.ENTER_FRAME,onCharSpriteEnterFrameHandler);
				}
				position="center"
			}else if(position=="center"){
				if(hasEventListener(MouseEvent.CLICK)){
					removeEventListener(MouseEvent.CLICK,onCenterImageClickHandler);
					removeEventListener(MouseEvent.CLICK,onLoaderClickHandler);
				}
				addEventListener(MouseEvent.CLICK,onBottomImageClickHandler);
				TweenLite.to(this,1.2,{y:stage.stageHeight-20});
				for(i=0;i<text_sp.numChildren;i++){
					text_sp.getChildAt(i).removeEventListener(Event.ENTER_FRAME,onCharSpriteEnterFrameHandler);
				}
				position="bottom"
			}else{
				if(hasEventListener(MouseEvent.CLICK)){
					removeEventListener(MouseEvent.CLICK,onBottomImageClickHandler);
				}
				TweenLite.to(this,1.2,{y:stage.stageHeight,onComplete:destroy});
			}
		}else{
			throw new Error();
		}
	}
	
	private function onTopImageClickHandler(event:MouseEvent):void{
		removeEventListener(MouseEvent.CLICK,onTopImageClickHandler);
		RSSReader(parent).scrollItems("down");
	}
	
	private function onCenterImageClickHandler(event:Event):void{
		removeEventListener(MouseEvent.CLICK,onCenterImageClickHandler);
		
		var index_x:Number=Math.round((this.mouseX-IMAGE_EDGE_WIDTH)/PIXEL_SIZE/IMAGE_SCALE);
		var index_y:Number=Math.round((this.mouseY-IMAGE_EDGE_WIDTH)/PIXEL_SIZE/IMAGE_SCALE);
		if(index_x<0){index_x=0;}else if(index_x>char_sp_array.length-1){index_x=char_sp_array.length-1;}
		if(index_y<0){index_y=0;}else if(index_y>char_sp_array[0].length-1){index_y=char_sp_array[0].length-1;}
		
		
		var cnt:Number=0;
		addEventListener(Event.ENTER_FRAME,function onClickEnterFrameHandler():void{
			for(var i:int=-cnt;i<=cnt;i++){
				if(!(index_x+i>=0&&index_x+i<char_sp_array.length)){continue;}
				if(i==-cnt||i==cnt){
					char_sp_array[index_x+i][index_y].addEventListener(Event.ENTER_FRAME,onCharSpriteClickEnterFrameHandler);
				}else{
					if(index_y+cnt-Math.abs(i)<char_sp_array[0].length){
						char_sp_array[index_x+i][index_y+cnt-Math.abs(i)].addEventListener(Event.ENTER_FRAME,onCharSpriteClickEnterFrameHandler);
					}
					if(index_y-(cnt-Math.abs(i))>=0){
						char_sp_array[index_x+i][index_y-(cnt-Math.abs(i))].addEventListener(Event.ENTER_FRAME,onCharSpriteClickEnterFrameHandler);
					}
				}
			}
			if(++cnt>80){removeEventListener(Event.ENTER_FRAME,onClickEnterFrameHandler);}
		});
		addEventListener(MouseEvent.CLICK,onLoaderClickHandler);
	}
	
	private function onLoaderClickHandler(event:MouseEvent):void{
		navigateToURL(new URLRequest(item["link"].toString()));
	}
	private function onCharSpriteClickEnterFrameHandler(event:Event):void{
		event.target.alpha-=0.2;
		
		loader_mask_sp.graphics.beginFill(0x000000,1-event.target.alpha);
		
		loader_mask_sp.graphics.drawRect(
			IMAGE_EDGE_WIDTH+Math.round((event.target.x-IMAGE_EDGE_WIDTH)*IMAGE_SCALE),
			IMAGE_EDGE_WIDTH+Math.round((event.target.y-IMAGE_EDGE_WIDTH)*IMAGE_SCALE),
			PIXEL_SIZE,PIXEL_SIZE);
		loader_mask_sp.graphics.endFill();
		
		if(event.target.alpha<=0){
			event.target.alpha=0;
			event.target.removeEventListener(Event.ENTER_FRAME,onCharSpriteClickEnterFrameHandler);
		}			
	}
	
	private function onBottomImageClickHandler(event:MouseEvent):void{
		removeEventListener(MouseEvent.CLICK,onBottomImageClickHandler);
		RSSReader(parent).scrollItems("up");
	}
	
	private static function createReducedBitmapData(loader:Loader):BitmapData{
		var reduced_bmd:BitmapData=new BitmapData(loader.width/PIXEL_SIZE,loader.height/PIXEL_SIZE,false);
		var matrix:Matrix=new Matrix();
		matrix.scale(1/PIXEL_SIZE,1/PIXEL_SIZE);
		reduced_bmd.draw(loader,matrix);
		
		return reduced_bmd;
	}
	
	private function createTextSprite(src_bmd:BitmapData,charArray:Array):Sprite{
		char_sp_array=new Array();
		var sp:Sprite=new Sprite();
		for (var x:int=0;x<src_bmd.width;x++){
			char_sp_array[x]=new Array();
			for (var y:int=0;y<src_bmd.height;y++){
				var c:int=src_bmd.getPixel(x,y);
				var b:int=(((c>>16)&255)+((c>>8)&255)+(c&255))/3;
				var index:int=Math.floor(b/255*(charArray.length-1));
				
				var tf:TextField=new TextField();
				tf.defaultTextFormat=RSSReader.TEXT_FORMAT;
				tf.textColor=c;
				tf.autoSize=TextFieldAutoSize.LEFT;
				tf.selectable=false;
				tf.text=charArray[index]["string"];
				tf.x-=(2+tf.textWidth/2);
				tf.y-=(tf.textHeight/2);
				
				var char_sp:Sprite=new Sprite();
				char_sp.addChild(tf);
				char_sp.x=x*PIXEL_SIZE-tf.x;
				char_sp.y=y*PIXEL_SIZE-tf.y;
				char_sp.filters=[GRAYSCALE_FILTER];
				
				sp.addChild(char_sp);
				char_sp_array[x][y]=char_sp;
			}
		}
		return sp;
	}
	
	private function onCharSpriteEnterFrameHandler(event:Event):void{
		if(Math.abs(event.target.mouseX)<HIT_RANGE&&Math.abs(event.target.mouseY)<HIT_RANGE){
			var distance:Number=HIT_RANGE_SQUARE-(Math.pow(event.target.mouseX,2)+Math.pow(event.target.mouseY,2));
			var scale:Number=Math.pow(distance/HIT_RANGE_SQUARE,2);
			scale=Math.floor(scale*100)/100;
			event.target.scaleX=1+scale*TEXT_MAGNIFICATION;
			event.target.scaleY=1+scale*TEXT_MAGNIFICATION;
			event.target.filters=[getGrayScaleFilter(scale)];
		}else if(event.target.scaleX>1){
			event.target.scaleX/=1.2;
			event.target.scaleY/=1.2;
			if(event.target.scaleX<1){
				event.target.scaleX=event.target.scaleY=1;
				event.target.filters=[getGrayScaleFilter(0)];
			}
		}
	}
	
	private function getGrayScaleFilter(val:Number):ColorMatrixFilter{
		var a:Number=1-2/3*(1-val);
		var b:Number=1/3*(1-val);
		return new ColorMatrixFilter(
			[a,b,b,0,0,
			 b,a,b,0,0,
			 b,b,a,0,0,
			 0,0,0,1,0]);
	}
}