LogoLogo
  • Home
  • Projects
  • About
  • Contact

OBO_FlashBox – LightBox in Flash (with added 3d)

Devon O. · December 06, 2008 · Actionscript, Flash · 16 comments
3

Just in for the holidays – a new LightBox JS implementation for Flash (with a Flash 10 3d Twist).

Here’s a quickie example made with Flex just to see what I’m on about. The main drawback seems to be the new Flash Player 10 3d features tend to blur the edges of the picture’s frame. Not entirely sure why that is, but If anyone can explain, please let me know and I’ll do what I can to fix it up.

If interested, the script is below. It requires TweenLite and the Tweener equations for the animation (I like to mix and match), though you’re welcome to rewrite it for another tweening engine.

The main FlashBox class:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package com.onebyonedesign.extras {
    
    import caurina.transitions.Equations;
    import com.onebyonedesign.extras.OBO_PreloadAni;
    import flash.display.DisplayObjectContainer;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.net.URLRequest;
    import flash.text.AntiAliasType;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.TextFormat;
    import gs.OverwriteManager;
    import gs.TweenLite;
    
    /**
     * LightBox for Flash flash. Requires TweenLite for animation.
     * @author Devon O.
     */
    public class OBO_FlashBox extends Sprite {
        
        private var _instructions:TextField;
        private static const INSTRUCTIONS_FORMAT:TextFormat = new TextFormat("_sans", 12, 0x000000);
        
        private var _cover:Sprite;
        private var _frame:Sprite;
        private var _frameHolder:Sprite;
        
        private var _parent:DisplayObjectContainer;
        private var _path:String;
        
        private var _preloader:OBO_PreloadAni;
        
        private var _loader:Loader;
        
        private var _imageWidth:int;
        private var _imageHeight:int;
        
        private static const COVER_COLOR:uint = 0x000000;
        private static const FRAME_COLOR:uint = 0xFFFFFF;
        
        /**
         *
         * @param    attachTo        DisplayObjectContainer that will "hold" the flashbox. Must be in the display list.
         * @param    pathToImage        String that describes the path to the image to load.
         */
        public function OBO_FlashBox(attachTo:DisplayObjectContainer, pathToImage:String):void {
            trace (pathToImage);
            _parent = attachTo;
            _path = pathToImage;
            mouseChildren = false;
            buttonMode = true;
            
            init();
        }
        
        private function init():void {
            OverwriteManager.init();
            initTextfield();
            initDisplay();
        }
        
        private function initTextfield():void {
            _instructions = new TextField();
            _instructions.defaultTextFormat = INSTRUCTIONS_FORMAT;
            _instructions.mouseEnabled = false;
            _instructions.selectable = false;
            _instructions.autoSize = TextFieldAutoSize.LEFT;
            _instructions.antiAliasType = AntiAliasType.ADVANCED;
            _instructions.text = "Click to close.";
        }
        
        private function initDisplay():void {
            _cover = drawCover(COVER_COLOR, .75, _parent.stage.stageWidth, _parent.stage.stageHeight);
            
            addChild(_cover);
            
            _frame = drawFrame(FRAME_COLOR, 1, 100, 100);
            
            _frameHolder = new Sprite();
            _frameHolder.x = _cover.width * .5;
            _frameHolder.y = _cover.height * .5;
            _frameHolder.addChild(_frame);
            _frameHolder.buttonMode = true;
            
            _preloader = new OBO_PreloadAni(10, 10, "Loading image...");
            _frame.addChild(_preloader);
            
            addEventListener(MouseEvent.CLICK, remove);
            _frameHolder.addEventListener(MouseEvent.CLICK, remove);
            
            _parent.addChild(this);
            _parent.addChild(_frameHolder);
            loadImage();
        }
        
        private function loadImage():void {
            _loader = new Loader();
            _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoad);
            _loader.load(new URLRequest(_path));
        }
        
        private function onImageLoad(event:Event):void {
            _frame.removeChild(_preloader);
            _imageHeight = Math.round(_loader.height + 40);
            _imageWidth = Math.round(_loader.width + 20);
            TweenLite.to(_frame, .3, { height:_imageHeight, ease:Equations.easeOutQuad } );
            TweenLite.to(_frame, .3, { width:_imageWidth, ease:Equations.easeOutQuad, delay:.3, onComplete:displayImage } );
        }
        
        private function displayImage():void {
            _loader.x = _loader.width * .5;
            _loader.y = -(_loader.height * .5 + 10);
            _loader.scaleX = -1;
            _loader.visible = false;
            _frameHolder.addChild(_loader);
            _instructions.x = 10 - _imageWidth * .5 + _instructions.textWidth;
            _instructions.y = _imageHeight * .5 - 20;
            _instructions.rotationY = 180;
            _instructions.visible = false;
            _frameHolder.addChild(_instructions);
            TweenLite.to(_frameHolder, .5, { rotationY:-180, onUpdate:checkRotation } );
        }
        
        private function checkRotation():void {
            if (_frameHolder.rotationY <= -90) {
                _loader.visible = true;
                _instructions.visible = true;
            }
        }
        
        private function drawCover(colour:uint, alpha:Number, w:Number, h:Number):Sprite {
            var s:Sprite = new Sprite();
            s.graphics.beginFill(colour, alpha);
            s.graphics.drawRect(0, 0, w, h);
            s.graphics.endFill();
            return s;
        }
        
        private function drawFrame(colour:uint, alpha:Number, w:Number, h:Number):Sprite {
            var s:Sprite = new Sprite();
            s.graphics.beginFill(colour, alpha);
            s.graphics.drawRect(-(w * .5), -(h * .5), w, h);
            s.graphics.endFill();
            return s;
        }
        
        private function remove(event:MouseEvent):void {
            _parent.removeChild(this);
            _parent.removeChild(_frameHolder);
        }
    }
}

And, while you can use any little graphic preloader you’d like, I used the one below:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
package com.onebyonedesign.extras {
    
    import flash.display.Sprite;
    import flash.geom.ColorTransform;
    import flash.geom.Transform;
    import flash.text.AntiAliasType;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.TextFormat;
    import flash.utils.Timer;
    import flash.events.TimerEvent;
    import flash.events.Event;
 
    public class OBO_PreloadAni extends Sprite {
        
        private var _r:Number;
        private var _numItems:uint;
 
        private var _p:Sprite;
        private var _items:Array;
        
        private var _timer:Timer;
        private var _ct:ColorTransform;
        private var _currItem:int;
        
        private var _words:String;
        
        public function OBO_PreloadAni(radius:Number, numItems:uint, message:String = "") {
            
            _r = radius;
            _numItems = numItems;
            _p = new Sprite();
            _words = message;
            
            _items = new Array();
            _currItem = 0;
            
            init();
        }
        
        private function init():void {
            addChild(_p);
            createItems();
            addText();
            startAnimation();
            addEventListener(Event.REMOVED_FROM_STAGE, kill);
        }
        
        private function createItems():void {
            var angleIncrement:Number = 360 / _numItems;
            for (var i:int=0; i <= _numItems; i++) {
                var item:Sprite = createItem(i);
                var degrees:Number  = (i * angleIncrement);
                var rads:Number = (degrees * Math.PI) / 180;    
                
                //end X and Y values for the card
                var tx:Number = Math.cos(rads) * _r;
                var ty:Number = Math.sin(rads) * _r;
                
                // get distance clip is from center
                var dx:Number = tx;
                var dy:Number = ty;
                // Computing the arctangent to find angle
                // atan2 is used to find the direction from one point to another in 2-dimension
                // Steradians (square radians) can be converted to square degrees by multiplying
                // by the square of the number of degrees in a radian = 57.2957795... degrees.
                // It is used to describe two-dimensional angular spans in three-dimensional space,
                item.rotation = Math.atan2(dy, dx) * 57.2957795;
                item.x = tx;
                item.y = ty;
                _items.push(item);
                
                _p.addChild(item);
            }
        }
        
        private function addText():void {
            if (_words) {
                var tf:TextField = new TextField();
                tf.selectable = false;
                tf.autoSize = TextFieldAutoSize.LEFT;
                tf.mouseEnabled = false;
                tf.defaultTextFormat = new TextFormat("_sans", 11);
                tf.antiAliasType = AntiAliasType.ADVANCED;
                tf.text = _words;
                tf.y = Math.round(_p.height / 2 + 5);
                tf.x = Math.round(- tf.textWidth / 2);
                addChild(tf);
            }
        }
        
        private function startAnimation():void {
            _timer = new Timer(40);
            _timer.addEventListener(TimerEvent.TIMER, updateColor);
            _timer.start();
        }
        
        private function updateColor(te:TimerEvent):void {
            // change old to black
            var t:Sprite = _items[_currItem];
            _ct = new ColorTransform();
            t.transform.colorTransform = _ct;
            
            if (++_currItem > _items.length - 1) _currItem = 1;
            
            // change new to reddish
            t = _items[_currItem];
            _ct = new ColorTransform();
            _ct.redMultiplier = 1;
            _ct.redOffset = 0x88;
            _ct.greenMultiplier = 0;
            _ct.blueMultiplier = 0;
            t.transform.colorTransform = _ct;
            
        }
        
        private function createItem(id:Number):Sprite {
            var r:Sprite = new Sprite();
            r.graphics.beginFill(0x000000);
            r.graphics.drawRect(0, 0, 8, 3);
            r.graphics.endFill();
            return r;
        }
        
        
        public function destroy():void {
            _timer.stop();
            _timer.removeEventListener(TimerEvent.TIMER, updateColor);
            _ct = new ColorTransform();
            _items.forEach(setBlack);
            _currItem = _items.length - 1;
            _timer = new Timer (20, _items.length);
            _timer.addEventListener(TimerEvent.TIMER, removeItem);
            _timer.addEventListener(TimerEvent.TIMER_COMPLETE, onDone);
            _timer.start();
        }
        
        private function setBlack(e:Sprite, i:uint, a:Array):void {
            e.transform.colorTransform = _ct;
        }
        
 
        private function removeItem(te:TimerEvent):void {
            _p.removeChild(_items[_currItem--]);
        }
        
        private function onDone(te:TimerEvent):void {
            _timer.removeEventListener(TimerEvent.TIMER, removeItem);
            _timer.removeEventListener(TimerEvent.TIMER_COMPLETE, onDone)
            dispatchEvent(new Event("onPlaDone"));
        }
        
        private function kill(event:Event):void {
            removeEventListener(Event.REMOVED_FROM_STAGE, kill);
            _timer.stop();
            _timer.removeEventListener(TimerEvent.TIMER, updateColor);
            
            _p = null;
            _items = null;
            _timer = null;
            _ct = null;
        }
    }
}

Unfortunately, to get the OBO_FlashBox class to play nicely with Flex, you need to create a little Flex “bridge” that extends UIComponent like so:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package  {
    
    import flash.events.Event;
    import mx.core.UIComponent;
    import com.onebyonedesign.extras.OBO_FlashBox;
    
    /**
     * little class to use OBO_FlashBox in Flex
     * @author Devon O.
     */
    public class FlexBox extends UIComponent {
        
        private var _pathToImage:String;
        
        public function FlexBox(pathToImage:String) {
            _pathToImage = pathToImage;
            if (stage) {
                init(null);
            } else {
                addEventListener(Event.ADDED_TO_STAGE, init)
            }
        }
        
        private function init(event:Event):void {
            removeEventListener(Event.ADDED_TO_STAGE, init)
            var _fb:OBO_FlashBox = new OBO_FlashBox(this, _pathToImage);
        }
    }
}

And finally, the mxml for the example shown:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
    <mx:Script>
        <![CDATA[
 
        import mx.events.ListEvent;
            
        [Bindable]
        [Embed(source="assets/thumbs/1.jpg")]
        public var thumb1:Class;
            
        [Bindable]
        [Embed(source="assets/thumbs/2.jpg")]
        public var thumb2:Class;
            
        [Bindable]
        [Embed(source="assets/thumbs/3.jpg")]
        public var thumb3:Class;
        
        [Bindable]
        [Embed(source="assets/thumbs/4.jpg")]
        public var thumb4:Class;
 
        [Bindable]
        [Embed(source="assets/thumbs/5.jpg")]
        public var thumb5:Class;
        
        [Bindable]
        [Embed(source="assets/thumbs/6.jpg")]
        public var thumb6:Class;
            
        [Bindable]
        [Embed(source="assets/thumbs/7.jpg")]
        public var thumb7:Class;
            
        [Bindable]
        [Embed(source="assets/thumbs/8.jpg")]
        public var thumb8:Class;
        
        [Bindable]
        [Embed(source="assets/thumbs/9.jpg")]
        public var thumb9:Class;
 
        [Bindable]
        [Embed(source="assets/thumbs/10.jpg")]
        public var thumb10:Class;
        
        [Bindable]
        [Embed(source="assets/thumbs/11.jpg")]
        public var thumb11:Class;
 
        [Bindable]
        [Embed(source="assets/thumbs/12.jpg")]
        public var thumb12:Class;
        
        private var _flexBox:FlexBox;
        
        private function displayImage(event:ListEvent):void {
            if (_flexBox && parent.contains(_flexBox)) {
                parent.removeChild(_flexBox);
                _flexBox = null;
            }
            _flexBox = new FlexBox(event.currentTarget.selectedItem.path);
            parent.addChild(_flexBox);
        }
        ]]>
    </mx:Script>
    <mx:Panel title="OBO_FlashBox Example" width="525" height="430">
        <mx:TileList id="CameraSelection" itemClick="displayImage(event)" height="100%" width="100%" maxColumns="4" rowHeight="125" columnWidth="125">
            <mx:dataProvider>
                <mx:Array>
                    <mx:Object label="Monkeys" icon="{thumb1}" path="images/large/1.jpg" />
                    <mx:Object label="Maniacs" icon="{thumb2}" path="images/large/2.jpg"/>
                    <mx:Object label="Dead" icon="{thumb3}" path="images/large/3.jpg"/>
                    <mx:Object label="Feast" icon="{thumb4}" path="images/large/4.jpg"/>
                    <mx:Object label="Cyclops" icon="{thumb5}" path="images/large/5.jpg"/>
                    <mx:Object label="House" icon="{thumb6}" path="images/large/6.jpg"/>
                    <mx:Object label="Beyond" icon="{thumb7}" path="images/large/7.jpg"/>
                    <mx:Object label="Bug" icon="{thumb8}" path="images/large/8.jpg"/>
                    <mx:Object label="Dead" icon="{thumb9}" path="images/large/9.jpg"/>
                    <mx:Object label="Zombies" icon="{thumb10}" path="images/large/10.jpg"/>
                    <mx:Object label="Hell" icon="{thumb11}" path="images/large/11.jpg"/>
                    <mx:Object label="Christmas" icon="{thumb12}" path="images/large/12.jpg"/>
                </mx:Array>
            </mx:dataProvider>
        </mx:TileList>
    </mx:Panel>
</mx:Application>

Hope it may be useful. Enjoy…

  Facebook   Pinterest   Twitter   Google+
flash 10flexlightbox
  • My God, It’s Full of Stars…
    March 23, 2010 · 0 comments
    1878
    8
    Read more
  • More Augmented Reality with HTML5 && Flash
    February 10, 2010 · 0 comments
    1907
    7
    Read more
  • Quick Sound Effects Generator
    May 12, 2010 · 5 comments
    2191
    5
    Read more
16 Comments:
  1. Nice example, as always!

    noponies · December 07, 2008
  2. error at _flexBox = new FlexBox(event.currentTarget.selectedItem.path);

    john · December 21, 2008
  3. Thank you, noponies..

    And what’s the error, john? I’m not seeing it thrown.

    Devon O. · December 22, 2008
  4. Very Nice, I have been searching all over for this, but all I’m getting is empty white boxes, I can’t seem to get the image to load in the flash box… same goes for your linked example?

    James · January 03, 2009
  5. Hey James,

    I apologize if this is a stupid question but are you using Flash CS4/Flash Player 10?

    Devon O. · January 03, 2009
  6. Apparently I’m the stupid one, I just upgraded to Flash 10 for Safari and now your demo appears to be working… although Flex Builder is now throwing an error in OB_FashBox.as:

    1119: Access of possibly undefined property rotationY through a reference with static type flash.display:Sprite.
    OBO_FlashBox.as line 128

    and

    1119: Access of possibly undefined property rotationY through a reference with static type flash.text:TextField.
    OBO_FlashBox.as line 121

    both seem to have issue with the rotationY function…

    James · January 03, 2009
  7. Aha. Now you’ll have to make sure you’re using the most recent Flex SDK. I don’t use Flex Builder (just FlashDevelop pointed towards the free SDK), so I couldn’t help you there, but it shouldn’t be too difficult to figure out.

    Devon O. · January 03, 2009
  8. what would I have to do to eliminate the flip effect?

    James · January 03, 2009
  9. Hey James, Just go through the displayImage() method of OBO_FlashBox.as and play with the settings. In that method, _loader is the picture and _instructions is the textfield that just says “click to close”. Change their x and y positions and get rid of the scaleX setting on the _loader. Don’t set their visible properties to false and get rid of the TweenLite call (that does the flip).

    Devon O. · January 04, 2009
  10. Thanks, I got it working, I didn’t realize that scaleX was actually flipping the image, it was driving me nuts..
    … you my friend, have officially earned Coffee on me :)

    James · January 04, 2009
  11. also for anyone else that stops by: To run these scripts in Flex Builder you will need to import fl.motion.Motion for the TweenLite calls (although I never got rotateY to work) – the file is available in your Flash install directory

    James · January 04, 2009
  12. Thank you for the info, James – and, moreover, thanks for the coffee!

    Devon O. · January 06, 2009
  13. hi that flash light box is seem good i want this

    pradeep · January 15, 2009
  14. All the code exammples are truncated to just what is showing – You can’t scroll to get the to rest

    :)

    Carl · September 18, 2010
  15. Last comment was due to the fact I was using Opera

    FireFox is OK
    :)

    Carl · September 18, 2010
  16. Thanks for the heads up, Carl. I never did test this new WP theme in Opera. Guess I shoulda.. :)

    Devon O. · September 18, 2010

Leave a Comment! Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Devon O. Wolfgang

AIR | Unity3D | AR/VR

Unity Certified Developer

Technical Reviewer of “The Essential Guide to Flash CS4 AIR Development” and “Starling Game Development Essentials”

Reviewer of “The Starling Handbook”

Unity Engineer at Touch Press.

Categories
  • Actionscript (95)
  • AIR (16)
  • Flash (99)
  • Games (7)
  • Liberty (13)
  • Life (53)
  • Shaders (20)
  • Unity3D (21)
Recent Comments
  • Devon O. on Unity Ripple or Shock Wave Effect
  • Feral_Pug on Unity Ripple or Shock Wave Effect
  • bavvireal on Unity3D Endless Runner Part I – Curved Worlds
  • Danielius Vargonas on Custom Post Processing with the LWRP
  • Luca G on Unity Ripple or Shock Wave Effect
Archives
  • December 2020 (1)
  • December 2019 (1)
  • September 2019 (1)
  • February 2019 (2)
  • December 2018 (1)
  • July 2018 (1)
  • June 2018 (1)
  • May 2018 (2)
  • January 2018 (1)
  • December 2017 (2)
  • October 2017 (1)
  • September 2017 (2)
  • January 2017 (1)
  • July 2016 (1)
  • December 2015 (2)
  • March 2015 (1)
  • September 2014 (1)
  • January 2014 (1)
  • August 2013 (1)
  • July 2013 (1)
  • May 2013 (1)
  • March 2013 (2)
  • December 2012 (1)
  • November 2012 (1)
  • September 2012 (3)
  • June 2012 (2)
  • May 2012 (1)
  • April 2012 (1)
  • December 2011 (2)
  • October 2011 (3)
  • September 2011 (1)
  • August 2011 (1)
  • July 2011 (1)
  • May 2011 (2)
  • April 2011 (2)
  • March 2011 (1)
  • February 2011 (1)
  • January 2011 (2)
  • December 2010 (3)
  • October 2010 (5)
  • September 2010 (1)
  • July 2010 (2)
  • May 2010 (5)
  • April 2010 (2)
  • March 2010 (7)
  • February 2010 (5)
  • January 2010 (5)
  • December 2009 (3)
  • November 2009 (1)
  • October 2009 (5)
  • September 2009 (5)
  • August 2009 (1)
  • July 2009 (1)
  • June 2009 (2)
  • May 2009 (6)
  • April 2009 (4)
  • March 2009 (2)
  • February 2009 (4)
  • January 2009 (1)
  • December 2008 (5)
  • November 2008 (2)
  • September 2008 (1)
  • August 2008 (6)
  • July 2008 (6)
  • June 2008 (9)
  • May 2008 (4)
  • April 2008 (3)
  • March 2008 (4)
  • February 2008 (9)
  • January 2008 (7)
  • December 2007 (6)
Copyright © 2017 Devon O. Wolfgang