Beautifl - Flash Gallery

Thumbnail : Butterfly (+animation)
Butterfly (+animation)
tencho 2011-02-14 MIT License

再生するにはFlash Playerが必要です。デスクトップのブラウザでご覧ください。

/**
 * Click : Zoom In
 * CTRL+Click : Zoom Out
 * Drag : Move
 * 1-5 : Somewhere
 */
package  {
    
    import com.bit101.components.*;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.geom.ColorTransform;
    import flash.geom.Point;
    import frocessing.color.ColorHSV;
    
    public class Study extends Sprite {
        
        private var _bg:Sprite = new Sprite();
        private var _bmp:Bitmap;
        private var _bmd:BitmapData;
        private var _buffer:BitmapData;
        private var _md:Mandelbrot;
        
        private var _animate:Boolean = true;
        private var _fade:Boolean = true;
        private var _deep:Boolean = false;
        private var _ctrl:Boolean = false;
        private var _isMouseDown:Boolean = false;
        private var _isDrag:Boolean = false;
        private var _staticScale:Number = 1;
        private var _animationScale:Number = 0.5;
        private var _centerRI:Point = new Point();
        private var _downRI:Point = new Point();
        private var _downXY:Point = new Point();
        private var _alphaBlend:ColorTransform = new ColorTransform(1, 1, 1, 0.15, 0, 0, 0, 0);
        private var _checks:Vector.<CheckBox> = new Vector.<CheckBox>();
        private var _timer:ClockTimer = new ClockTimer();
        private var _drawScale:Number;
        private var _zoom:Number;
        
        public function Study() {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            stage.frameRate = 60;
            
            _bmp = new Bitmap(_bmd, "auto", true);
            setCanvasScale(_animationScale);
            addChild(_bg);
            addChild(_bmp);
            createButtons();
            _bg.graphics.beginFill(0);
            _bg.graphics.drawRect(0, 0, 465, 465);
            
            _timer.start();
            _timer.time = 2000;
            _md = new Mandelbrot();
            _md.colors.length = 0;
            for (var c:int = 0; c < 256; c++)
                _md.colors[c] = !c ? 0xFFFFFFFF : (c < 128)    ? new ColorHSV(70 - 40 * c / 128, 1, 1).value32 : new ColorHSV(30, 1, 2 - c / 128).value32;
            _bg.addEventListener(MouseEvent.MOUSE_DOWN, onDownStage);
            stage.addEventListener(MouseEvent.MOUSE_MOVE, onDragStage);
            stage.addEventListener(MouseEvent.MOUSE_UP, onUpStage);
            
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
            stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyInput);
            stage.addEventListener(KeyboardEvent.KEY_UP, onKeyInput);
            resetPosition();
            updateSettings();
        }
        
        private function createButtons():void {
            Style.PANEL = 0x222222;
            new Panel(this, 465 - 90, 0).setSize(90, 105);
            var vox:VBox = new VBox(this, 465 - 80, 6);
            Style.LABEL_TEXT = 0xFFFFFF;
            Style.BACKGROUND = 0x666666;
            new FPSMeter(vox, 0, 0);
            var labels:Array = ["ANIMATION", "BLUR", "DEEP"];
            for (var i:int = 0; i < labels.length; i++)
                _checks[i] = new CheckBox(vox, 0, 0, labels[i], updateSettings);
            Style.LABEL_TEXT = 0;
            new PushButton(vox, 0, 10, "RESET", resetPosition).setSize(70, 18);
            _checks[0].selected = _animate;
            _checks[1].selected = _fade;
            _checks[2].selected = _deep;
        }
        
        private function onKeyInput(e:KeyboardEvent):void {
            if (e.type == KeyboardEvent.KEY_UP) {
                switch(e.keyCode) {
                    ///case 32: System.setClipboard("jump(" + _centerRI.x.toFixed(String(int(_zoom)).length+2) + ", " + _centerRI.y.toFixed(String(int(_zoom)).length+2) + ", " + _zoom.toFixed(1) + ", " + _timer.time + ", "+_deep+");"); break;
                    case 49: case  97: jump( -0.32295, 0.000975, 0.8, 108841, false); break;
                    case 50: case  98: jump(-0.37453, 1.16594, 46, 165175, false); break;
                    case 51: case  99: jump(0.40441, -0.09875, 1995, 73081, true); break;
                    case 52: case 100: jump(-0.77836, 0.00102, 525, 38564, true); break;
                    case 53: case 101: jump(0.79734, 0.06116, 288, 34733, true); break;
                }
            }
            _ctrl = e.ctrlKey;
        }
        
        private function jump(x:Number, y:Number, zoom:Number, time:int, deep:Boolean):void {
            _timer.time = time;
            _centerRI = new Point(x, y);
            _zoom = zoom;
            _checks[0].selected = false;
            _checks[2].selected = deep;
            updateSettings();
            draw(true, _fade);
        }
        
        private function resetPosition(e:MouseEvent = null):void {
            _centerRI = new Point( -0.1, 0);
            _zoom = 0.7;
            draw(true, _fade);
        }
        
        private function updateSettings(e:Event = null):void {
            _animate = _checks[0].selected;
            _fade = _checks[1].selected;
            _deep = _checks[2].selected;
            _timer.setPlaying(_animate);
            _md.iteration = _deep? 120 : 30;
            setCanvasScale(_animate? _animationScale : _staticScale);
            draw(true, false);
        }
        
        private function onEnterFrame(e:Event):void {
            draw(_animate, _fade);
        }
        
        private function setCanvasScale(scale:Number):void {
            _drawScale = scale;
            if(_bmd) _bmd.dispose();
            if(_buffer) _buffer.dispose();
            _bmd = new BitmapData(465 * scale, 465 * scale, false, 0);
            _buffer = new BitmapData(465 * scale, 465 * scale, true, 0);
            _bmp.bitmapData = _bmd;
            _bmp.width = _bmp.height = 465;
        }
        
        private function onDownStage(e:MouseEvent):void {
            _isMouseDown = true;
            _isDrag = false;
            _downRI = _centerRI.clone();
            _downXY = new Point(mouseX, mouseY);
        }
        
        private function onUpStage(e:MouseEvent):void {
            if (!_isMouseDown) return;
            _isMouseDown = false;
            if (!_isDrag) {
                var m:int = _ctrl? -1 : 1;
                var tx:Number = (mouseX - _bmp.width / 2) * _md.SX / _zoom * m;
                var ty:Number = (mouseY - _bmp.height / 2) * _md.SY / _zoom * m;
                _centerRI.offset(tx, ty);
                _zoom *= Math.pow(1.5, m);
            }
            if (!_animate) setCanvasScale(_staticScale);
            draw(true, false);
        }
        
        private function onDragStage(e:MouseEvent):void {
            if (!_isMouseDown) return;
            if (!_isDrag) {
                if (Point.distance(new Point(_bmp.mouseX, _bmp.mouseY), _downXY) > 2) {
                    setCanvasScale(_animationScale);
                    draw(true, false);
                    _isDrag = true;
                }
                return;
            }
            _centerRI.x = _downRI.x - (mouseX - _downXY.x) * _md.SX / _zoom;
            _centerRI.y = _downRI.y - (mouseY - _downXY.y) * _md.SY / _zoom;
            if (!_animate) draw(true, _fade);
        }
        
        public function draw(calc:Boolean = true, fade:Boolean = true):void {
            if (calc) {
                var r:Number = _timer.time  * 0.007;
                _md.t = Math.sin(Math.PI / 180 * r*0.5) * 2;
                _md.x0 = Math.cos(Math.PI / 180 * r) * 0.8;
                _md.y0 = (Math.sin(Math.PI / 180 * r) + 2) * 0.2;
                _buffer.setVector(_bmd.rect, _md.getPixelsByCenter(_centerRI.x, _centerRI.y, _zoom * _drawScale, _zoom * _drawScale, _buffer.width, _buffer.height));
                if (fade) _buffer.colorTransform(_buffer.rect, _alphaBlend);
            }
            _bmd.copyPixels(_buffer, _buffer.rect, new Point(0, 0), null, null, true);
        }
        
    }
    
}

import flash.geom.Rectangle;
import flash.utils.getTimer;
import frocessing.color.ColorHSV;

class ClockTimer {
    
    private var _time:int = 0;
    private var _start:int = 0;
    private var _isPlaying:Boolean = false;
    
    public function get isPlaying():Boolean { return _isPlaying; }
    public function get time():int { return (!_isPlaying)? _time : _time + getTimer() - _start; }
    public function set time(value:int):void { setTime(value); }
    
    public function ClockTimer() {
    }
    
    public function reset():void {
        setTime(0);
    }
    
    private function setTime(value:int):void {
        _time = value;
        _start = getTimer();
    }
    
    public function setPlaying(play:Boolean):void {
        play? start() : stop();
    }
    
    public function start():void {
        if (_isPlaying) return;
        _start = getTimer();
        _isPlaying = true;
    }
    
    public function stop():void {
        _time = time;
        _isPlaying = false;
    }
    
}

class Mandelbrot {
    
    public var iteration:int = 100;
    public var t:Number = 2;
    public var x0:Number = 0;
    public var y0:Number = 0;
    public var colors:Vector.<uint> = new Vector.<uint>();
    public const SX:Number = 2.6 / 500;
    public const SY:Number = 2.6 / 500;
    
    public function Mandelbrot() {
        for (var i:int = 0; i < 360; i++)
            colors[i] = !i? 0xFF000000 : new ColorHSV(i, 0.8, 1.4).value32;
    }
    
    public function getPixelsByCenter(x:Number, y:Number, scaleX:Number = 1, scaleY:Number = 1, width:int = 465, height:int = 465):Vector.<uint> {
        var w:Number = SX / scaleX * width;
        var h:Number = SY / scaleY * height;
        return getPixels(new Rectangle(x - w / 2, y - h / 2, w, h), width, height);
    }

    public function getPixels(rect:Rectangle, width:int = 465, height:int = 465):Vector.<uint> {
        var i:int = 0, w:int, h:int, n:int, m:Number, dx:Number, dy:Number, cx:Number, cy:Number, x1:Number, y1:Number, x2:Number, y2:Number;
        var pixels:Vector.<uint> = new Vector.<uint>(width * height, true);
        dx = rect.width / width, dy = rect.height / height;
        cy = rect.y
        for (h = height; h > 0; h--) {
            cy += dy;
            cx = rect.x;
            for (w = width; w > 0; w--) {
                cx += dx;
                x1 = x0, y1 = y0;
                for (n = iteration; n > 0 && (x1 * x1 + y1 * y1) <= 100; n--) {
                    m = y1? x1 / y1 : Number.MAX_VALUE;
                    x2 = x1 * x1 - y1 * y1 + cy * m;
                    y2 = t * x1 * y1 + cx;
                    x1 = x2, y1 = y2;
                }
                pixels[i++] = colors[n / iteration * colors.length | 0];
            }
        }
        return pixels;
    }
    
}