Main.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
    creationComplete="init(event)"
    width="550"
    height="400"
    frameRate="24"
    backgroundColor="#101010" viewSourceURL="srcview/index.html">

    <mx:Spacer height="100%"/>
    <mx:Canvas id="_canvas" height="100%"/>
    <mx:VBox height="20%">
        <mx:HSlider
            id="_slider"
            width="200"
            labels="BPM" 
            minimum="120" 
            maximum="150"
            tickInterval="5"
            change="onSliderChange(event)"/>
    </mx:VBox>
    
    <mx:Script>
        <![CDATA[
            /**
             * Requires the following libraries, BeatTimer and Tweener.
             * 
             * @see http://www.libspark.org/wiki/BeatTimer
             * @see http://code.google.com/p/tweener/
             */ 
            import org.libspark.utils.media.BeatTimer;
            import caurina.transitions.Tweener;
            import com.borealkiss.display.FilterDrawer;
            import com.borealkiss.display.ImageBackground;
            
            private var _timer:BeatTimer;
            private var _drawer:FilterDrawer;
            private static const MAX_RAD:Number = 150;
            private static const MIN_RAD:Number = 100;
            
            private function init(e:Event):void{
                _timer = new BeatTimer();
                _timer.start(_slider.value);
                this.addEventListener(Event.ENTER_FRAME,onEnterFrame);
                
                var background:ImageBackground = new ImageBackground();
                _canvas.rawChildren.addChild(background);
                _drawer = new FilterDrawer(MIN_RAD,background);
                _canvas.rawChildren.addChild(_drawer);
            }
            
            private function onEnterFrame(e:Event):void{
                _drawer.update(_drawer.rad);
                _timer.update();
                if (_timer.isOnBeat){
                    _drawer.rad = MAX_RAD;
                    Tweener.addTween(_drawer, {rad:MIN_RAD, time:1, transition:"EaseOutExpo"});
                }
            }
            
            private function onSliderChange(e:Event):void{
                _timer.start(int(e.target.value));
            }
        ]]>
    </mx:Script>
</mx:Application>

FilterDrawer.as

package com.borealkiss.display{
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.BitmapDataChannel;
    import flash.geom.Point;   
    import flash.geom.Rectangle;
    import flash.filters.DisplacementMapFilter;
    
    public class FilterDrawer extends Sprite{
        
        private var _rad:Number;        //Radius of the filtered area
        private var _background:Bitmap;    //Background image
        private var _fMap:Bitmap;        //Filter
        
        /**
         * Constructor
         * 
         * @param rad Radius of the filtered area.
         * @param target Background image
         */ 
        public function FilterDrawer(rad:Number,target:Bitmap){
            _rad = rad;
            _background = target;
            init();
        }
        
        public function get rad():Number{
            return _rad;
        }
        
        public function set rad(value:Number):void{
            _rad = value;
        }
        
        private function init():void{
            _fMap = new Bitmap();
            addChild(_fMap);
            update(_rad);
        }
        
        public function update(size:Number):void{
            //Clear filters
            _fMap.filters = [];
            
            var bmpd:BitmapData = _fMap.bitmapData = new BitmapData(2*size,2*size);
            var rect:Rectangle = new Rectangle( _background.width/2-bmpd.width/2,
                                                _background.height/2-bmpd.height/2,
                                                bmpd.width,
                                                bmpd.height);
            bmpd.copyPixels(_background.bitmapData,rect,new Point(0,0));
            _fMap.x = - bmpd.width/2;
            _fMap.y = - bmpd.height/2;
            
            //Set filters
            var lens:BitmapData = createMap(size);
            var dispFilter:DisplacementMapFilter = new DisplacementMapFilter(
                lens,new Point(0,0),BitmapDataChannel.RED,BitmapDataChannel.BLUE,size,size);
            _fMap.filters = [dispFilter];
        }
        
        /**
         * Fisheye-like filter.
         * @see http://yamasv.blog92.fc2.com/blog-entry-100.html
         */ 
        private function createMap(r:int):BitmapData{
            var diameter:int = 2*r;
            var bmp:BitmapData = new BitmapData(diameter, diameter, false, 0x808080);
            for(var j:int = 0; j < diameter; j++){
                for(var i:int = 0; i < diameter; i++){
                    var ii:int = i - r;
                    var jj:int = j - r;
                    var distance:Number = Math.sqrt(ii*ii+jj*jj);
                    if(distance < r){
                        var v:Number = r*Math.asin(distance/r);
                        var theta:Number = Math.abs(Math.atan((j-r)/(i-r)));
                        var offsetR:int = (i > r) ? 
                            (v-distance)*Math.cos (theta) : -1*(v-distance)*Math.cos(theta);
                        var offsetB:int = (j > r) ? 
                            (v-distance)*Math.sin(theta) : -1*(v-distance)* Math.sin(theta);
                        var colR:int = 128 + offsetR;
                        var colB:int = 128 + offsetB;
                        bmp.setPixel(i, j, (colR << 16) + colB);
                    }
                }
            }
            return bmp;
        }
    }
}

ImageBackground.as

package com.borealkiss.display{
    import mx.core.BitmapAsset;
    
    /**
     * Background image
     */ 
    [(source="assets/curly.png")]
    public class ImageBackground extends BitmapAsset{
        public function ImageBackground(){
            this.x = -this.width/2;
            this.y = -this.height/2;    
        }
    }
}
Powered by blog Boreal Kiss 2008.