While catching up on various blog posts earlier today, I ran across this very nice example of a new Flash component which utilizes Papervision3D. As wonderful as it is, my first thought was, hey, you could do something like that natively in Flash 10 – which is exactly what I sat down and did.
Now, my example is not nearly as lovely as the component example and a good deal of the code I’m about to share is chocked full hard coded kludge, but it was kind of a rush job (’bout an hour’s worth of work) and was really just me seeing if it could be done. There’s a chance I’ll clean this up and redistribute at a later date – maybe a future component of my own. Until then however, here’s something to play around with, if anyone’s interested. Bear in mind, this would just as easily support video files – I’m just trying save a little bandwidth:
First, here is a small portion of the .xml being loaded, just to give the idea (yes, these are flicks from my personal stash):
EDIT: Seems after updating wordpress, my code highlighter will no longer support xml and wordpress throws in random tags here and there. Thanks WP..
The xml only contains a root node and several “movie” nodes. Each movie node contains an “image” node (a path to the .jpg file) and a “link” node (a path to an Amazon page). And that’s it…
The following is the class used for the thumbnail images. It basically just sticks an image inside a smoothed bitmap instance, resizes it to a standard size, stores a link URL, and adds some nice little roll over/out effects with the help of Tweener:
package {
import caurina.transitions.Tweener;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.filters.GlowFilter;
import flash.geom.Matrix;
import flash.net.navigateToURL;
import flash.net.URLRequest;
public class ThumbNail extends Sprite {
private var _imageWidth:int;
private var _imageHeight:int;
private var _link:String;
public function ThumbNail(w:int, h:int, image:DisplayObject, link:String = null):void {
_imageWidth = w;
_imageHeight = h;
_link = link;
createThumb(image);
}
private function createThumb(img:DisplayObject):void {
var bmd:BitmapData = new BitmapData(img.width, img.height);
bmd.draw(img);
img = null;
var bmp:Bitmap = new Bitmap(bmd, "auto", true);
bmp.width = _imageWidth;
bmp.height = _imageHeight;
var s:Sprite = new Sprite();
s.addChild(bmp);
s.mouseChildren = false;
s.x -= bmp.width * .5;
s.y -= bmp.height * .5;
s.filters = [new GlowFilter(0x000000, .75, 0, 0, 16, 1, true)];
s.addEventListener(MouseEvent.ROLL_OVER, rollOverHandler);
s.addEventListener(MouseEvent.ROLL_OUT, rollOutHandler);
s.addEventListener(MouseEvent.CLICK, clickHandler);
addChild(s);
}
// mouse events
private function rollOverHandler(event:MouseEvent):void {
var glow:GlowFilter = event.currentTarget.filters[0];
Tweener.addTween(glow, { blurY:32, time:.25, onUpdate:tweenBlur, onUpdateParams:[glow, event.currentTarget] } );
}
private function rollOutHandler(event:MouseEvent):void {
var glow:GlowFilter = event.currentTarget.filters[0];
Tweener.addTween(glow, { blurY:0, time:.25, onUpdate:tweenBlur, onUpdateParams:[glow, event.currentTarget] } );
}
private function clickHandler(event:MouseEvent):void {
navigateToURL(new URLRequest(_link), "_blank");
}
private function tweenBlur(glow:GlowFilter, s:Sprite):void {
s.filters = [glow];
}
}
}
This is the main spinning wall of images here. Basically what this boils down to is a Sprite that adds instances of the above ThumbNail class to the display list and arranges them in a 3d circular pattern.
package {
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLRequest;
public class CurvedImageWall extends Sprite {
private var _thumbnailWidth:int;
private var _thumbnailHeight:int;
private var _radius:int;
private var _currentLoadedImage:int;
private var _numImages:int;
private var _imageList:XMLList;
private var _linkList:XMLList;
public function CurvedImageWall(imgWidth:int, imgHeight:int, imgList:XMLList):void {
_thumbnailWidth = imgWidth;
_thumbnailHeight = imgHeight;
_imageList = imgList.image;
_linkList = imgList.link;
_numImages = _imageList.length();
_currentLoadedImage = 0;
// a little KLUDGE to play with
_radius = ((_numImages * _thumbnailWidth) / 2 * Math.PI) / 9.5;
loadImage(_imageList[_currentLoadedImage]);
}
private function loadImage(imageURL:String):void {
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageHandler);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, imageHandler);
loader.load(new URLRequest(imageURL));
}
private function imageHandler(event:*):void {
event.currentTarget.removeEventListener(Event.COMPLETE, imageHandler);
event.currentTarget.removeEventListener(IOErrorEvent.IO_ERROR, imageHandler);
if (event is IOErrorEvent) {
// trace ("couldn't load image #" + _currentLoadedImage);
} else if (event is Event) {
// image has loaded add it to 3d circle
var angleIncrement:Number = 360 / _numImages;
var tn:ThumbNail = new ThumbNail(_thumbnailWidth, _thumbnailHeight, event.currentTarget.content, _linkList[_currentLoadedImage]);
var degrees:Number = (_currentLoadedImage * angleIncrement);
var rads:Number = (degrees * Math.PI) / 180;
var tx:Number = Math.cos(rads) * _radius;
var tz:Number = Math.sin(rads) * _radius;
tn.x = tx;
tn.z = tz;
tn.rotationY = Math.atan2(tx, tz) * 57.2957795;
addChild(tn);
}
if (_currentLoadedImage++ < _numImages)
loadImage(_imageList[_currentLoadedImage]);
}
}
}
Finally, in the document class, main.as, we add an instance of the CurvedImageWall and set it spinning around in an ENTER_FRAME Event based on mouse position.
package {
import flash.display.GradientType;
import flash.display.Loader;
import flash.display.SpreadMethod;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.filters.DropShadowFilter;
import flash.geom.Matrix;
import flash.net.URLLoader;
import flash.net.URLRequest;
/**
* Example of circular curved 3d image wall in flash player 10
* @author Devon O.
*/
[SWF(width="500", height="400", backgroundColor="#000000", framerate="31")]
public class main extends Sprite {
private static const THUMB_WIDTH:int = 210;
private static const THUMB_HEIGHT:int = 300;
private var _wall:CurvedImageWall;
private var _numImages:int;
private var _centerX:Number;
private var _centerY:Number;
private var _rotationSpeed:Number;
public function main():void {
init();
}
private function init():void {
createBackground();
loadXML();
}
private function createBackground():void {
var filltype:String = GradientType.RADIAL;
var colors:Array = [0x000000, 0x696969];
var alphas:Array = [1, 1];
var ratios:Array = [0x00, 0xFF];
var mat:Matrix = new Matrix();
mat.createGradientBox(stage.stageWidth, stage.stageHeight);
var spread:String = SpreadMethod.REFLECT;
graphics.beginGradientFill(filltype, colors, alphas, ratios, mat, spread);
graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
graphics.endFill();
}
private function loadXML():void {
var ul:URLLoader = new URLLoader(new URLRequest("movies.xml"));
ul.addEventListener(IOErrorEvent.IO_ERROR, xmlHandler);
ul.addEventListener(Event.COMPLETE, xmlHandler);
}
private function xmlHandler(event:*):void {
if (event is IOErrorEvent) {
//trace ("couldn't load xml");
} else if (event is Event) {
// xml has loaded - create image wall
var movieXML:XML = new XML(event.currentTarget.data);
var movieList:XMLList = movieXML.movie;
_wall = new CurvedImageWall(THUMB_WIDTH, THUMB_HEIGHT, movieList);
_centerX = stage.stageWidth * .5;
_centerY = stage.stageHeight * .5;
_wall.x = _centerX;
_wall.y = _centerY;
addChild(_wall);
_wall.addEventListener(Event.ENTER_FRAME, frameHandler);
}
}
private function frameHandler(event:Event):void {
var wall:CurvedImageWall = event.currentTarget as CurvedImageWall;
wall.z = (stage.mouseY - _centerY) - 200;
_rotationSpeed = (_centerX - stage.mouseX) / 75;
wall.rotationY += _rotationSpeed;
wall.rotationX = (_centerX - stage.mouseX) / 100;
wall.rotationZ = (_centerX - stage.mouseX) / 100;
}
}
}
And all that yields (requires the Flash Player 10 plugin to view)…
[kml_flashembed movie=”https://blog.onebyonedesign.com/wp-content/uploads/2008/06/imagewall.swf” height=”400″ width=”500″ /]
Hope this might inspire something a little better. If so, share.