flash on 2012-4-17

by tepe
package {
♥0 | Line 451 | Modified 2012-04-19 17:14:02 | MIT License
play

ActionScript3 source code

/**
 * Copyright tepe ( http://wonderfl.net/user/tepe )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/tws0
 */

// forked from naoto5959's お絵描きツール
package
{
    import flash.display.*;
    import flash.events.*;
    import flash.text.*;

    [SWF(width = "465", height = "465", backgroundColor = "0x000000", frameRate = "60")] 
    public class SimpleDrawing extends Sprite  {
        
        private static const CANVAS_WIDTH:Number = 435;
        private static const CANVAS_HEIGHT:Number = 465;
        //private static const RECOVERBLE:Number = 100;//リドゥ回数
        
        public function SimpleDrawing() {
            var background:Sprite = new Sprite();//背景
            background.graphics.beginFill(0xffffff,1);
            background.graphics.drawRect(0,0,CANVAS_WIDTH, CANVAS_HEIGHT);
            
            //キャンバス
            var canvas:Canvas = new Canvas(CANVAS_WIDTH, CANVAS_HEIGHT, background);
            canvas.attach("pen", new PenTool());
            canvas.change("pen");
            canvas.attach("brush",new BrushTool());
            //canvas.change("brush");
            canvas.options = {thickness:10, color:0x000000,alpha:0.5};//太さ、カラー,透過率
            canvas.activate();

            addChild(canvas);
            
            
            

            //リドゥボタン
            var btn3:Sprite = new Sprite();
            btn3.graphics.beginFill(0xff00ff);
            btn3.graphics.drawRect(0,0,30, 30);
            btn3.x = canvas.width-30;
            btn3.y = 0;
            btn3.addEventListener(MouseEvent.CLICK,
                function(event:MouseEvent):void{
                                canvas.undo();//リドゥメソッド
            });
            addChild(btn3);
            
            var txt3:TextField = new TextField();
            txt3.x = txt3.y = 0;
            txt3.autoSize = TextFieldAutoSize.LEFT;
            txt3.text = "戻る";
            txt3.mouseEnabled = false;
            btn3.addChild(txt3);
            


            //リドゥボタン
            var btn_recover:Sprite = new Sprite();
            btn_recover.graphics.beginFill(0xff0000);
            btn_recover.graphics.drawRect(0,0,30, 30);
            btn_recover.x = canvas.width;
            btn_recover.y = 0;
            btn_recover.addEventListener(MouseEvent.CLICK,
                function(event:MouseEvent):void{
                                canvas.redo();//リドゥメソッド
            });
            var txt_recover:TextField = new TextField();
            txt_recover.x = txt_recover.y = 0;
            txt_recover.autoSize = TextFieldAutoSize.LEFT;
            txt_recover.text = "進む";
            txt_recover.mouseEnabled = false;
            btn_recover.addChild(txt_recover);
            addChild(btn_recover);




            //クリアボタン
            var btn_recoverAll:Sprite = new Sprite();
            btn_recoverAll.graphics.beginFill(0x00ff00);
            btn_recoverAll.graphics.drawRect(0,0,30, 30);
            btn_recoverAll.x = canvas.width;
            btn_recoverAll.y = btn_recover.height;
            btn_recoverAll.addEventListener(MouseEvent.CLICK,
                function(event:MouseEvent):void {
                                canvas.recoverAll();//クリアメソッド
            });
            
            var txt_recoverAll:TextField = new TextField();
            txt_recoverAll.x = txt_recoverAll.y = 0;
            txt_recoverAll.autoSize = TextFieldAutoSize.LEFT;
            txt_recoverAll.text = "消す";
            txt_recoverAll.mouseEnabled = false;
            btn_recoverAll.addChild(txt_recoverAll);

            addChild(btn_recoverAll);
            
            //クリアボタン
            var btn2:Sprite = new Sprite();
            btn2.graphics.beginFill(0xaaff00);
            btn2.graphics.drawRect(0,0,30, 30);
            btn2.x = canvas.width;
            btn2.y = 60;
            btn2.addEventListener(MouseEvent.CLICK,
                function(event:MouseEvent):void {
                                canvas.change("brush");
                                canvas.options = {thickness:40, color:0xff0000,alpha:0.2};//太さ、カラー
            });
            
            addChild(btn2);
        }
    }    
}



//-----------------------------------------------------
import flash.display.*;
import flash.events.*;

/**
 * drawing canvas
 * @author naoto koshikawa
 */
class Canvas extends Sprite{
    private var _cache:Sprite;
    private var _mask:Shape;
    private var _background:Bitmap;
    private var _original:BitmapData;
    private var _history:Array;
    private var _length:int;
    private var _recoverableCount:uint;
    private var _width:Number;
    private var _height:Number;
    
    private var _currentTool:ITool;//使用中のツール
    public function get currentTool():ITool    {
        return _currentTool;
    }
    
    private var _tools:Object;
    
    public function set options(options:Object):void{
        if (_currentTool) _currentTool.options = options;
    }
    
    public function get recoverable():Boolean{
        return (_length) ? true:false;
    }
    
    private var _recoverableAll:Boolean;
    public function get recoverableAll():Boolean{
        return _recoverableAll;
    }
    
    //コンストラクタ
    public function Canvas(w:Number, h:Number, background:IBitmapDrawable, recoverableCount:uint = 0){
        _tools = { };
        _history = [];
        _recoverableAll = false;
        _recoverableCount = recoverableCount;
        _width = w;
        _height = h;
        _cache = new Sprite();
        _cache.graphics.beginFill(0, 0);
        _cache.graphics.drawRect(0, 0, _width, _height);
        addChildAt(_cache, 0);
        
        _mask = new Shape();
        _mask.graphics.beginFill(0, 0);
        _mask.graphics.drawRect(0, 0, _width, _height);
        mask = _mask;
        addChildAt(_mask, 0);
        
        if (background) updateBackground(background);
    }
    
    public function activate():void{
        addEventListener(MouseEvent.MOUSE_DOWN, mouseDownListener);
    }
    
    public function inactivate():void{
        removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownListener);
        removeEventListener(MouseEvent.MOUSE_UP, mouseUpListener);
        removeEventListener(MouseEvent.MOUSE_OUT, mouseUpListener);
        removeEventListener(Event.ENTER_FRAME, enterFrameListener);
    }
    
    public function getDrawingData():BitmapData{
        return getBitmapData(this);
    }
    
    public function stack(displayObject:DisplayObject):void{
        while(_history.length>_length){
            _history.pop();
        }
        _history.push(displayObject);
        _length = _history.length;
        if (_length <= _recoverableCount) return;
        if(_recoverableCount==0)return;
        var i:uint;
        for (i = 1; i < _length; i++){
            _history[i]["visible"] = false;
        }
        updateBackground(this);
        _history.shift();
        _length--;
        _cache.removeChildAt(0);
        
        for (i = 0; i < _length; i++){
            _history[i]["visible"] = true;
        }
    }
    
    //ツール登録
    public function attach(key:String, tool:ITool):String{
        if (!_tools[key]) _tools[key] = tool;
        return key;
    }
    
    //ツール選択
    public function change(key:String):void{
        if (_tools[key]) _currentTool = _tools[key];
    }
    
    //アンドゥ
    public function undo():void{
        if (_length){
            trace(_length);
            _cache.removeChildAt(--_length);
            //_history.pop();
        }
    }
    //リドゥ
    public function redo():void{
        if(_length<_history.length){
            _cache.addChildAt(_history[_length], _length); 
            _length++;
        }

    }

    
    //キャンバスクリア
    public function recoverAll():void{
        for (var i:uint = 0; i < _length; i++){
            _cache.removeChildAt(0);
        }
        _history = [];
        _length = 0;
        
        if (_background && contains(_background)) removeChild(_background);
        _background = new Bitmap(_original);
        addChildAt(_background, 0);
        _recoverableAll = false;
    }
    
    //背景更新
    private function updateBackground(background:IBitmapDrawable):void{
        var bitmapData:BitmapData = getBitmapData(background);
        if (!_original) _original = bitmapData;
        if (_background && contains(_background)) removeChildAt(0);
        _background = new Bitmap(bitmapData);
        addChildAt(_background, 0);
    }
    
    
    private function getBitmapData(background:IBitmapDrawable):BitmapData{
        var bitmapData:BitmapData = new BitmapData(_width, _height);
        bitmapData.draw(background);
        return bitmapData;
    }
    
    //マウスダウン
    private function mouseDownListener(event:MouseEvent):void{
        var e:DrawingEvent = new DrawingEvent(DrawingEvent.START_DRAWING, true, true, mouseX, mouseY);
        dispatchEvent(e);
        if (!e.isDefaultPrevented()){
            addEventListener(MouseEvent.MOUSE_UP, mouseUpListener);
            addEventListener(MouseEvent.MOUSE_OUT, mouseUpListener);
            addEventListener(Event.ENTER_FRAME, enterFrameListener);
            if (_currentTool){
                _currentTool.start(mouseX, mouseY);
                _cache.addChildAt(_currentTool.displayObject, _length);
                _recoverableAll = true;
            }
        }
    }
    
    //エンターフレーム
    private function enterFrameListener(event:Event):void{
        var e:DrawingEvent = new DrawingEvent(DrawingEvent.MOVE_DRAWING, true, true, mouseX, mouseY);
        dispatchEvent(e);
        if (!e.isDefaultPrevented()){
            if (_currentTool) _currentTool.move(mouseX, mouseY);
        }
    }
    
    //マウスアップ
    private function mouseUpListener(event:MouseEvent):void{
        var e:DrawingEvent = new DrawingEvent(DrawingEvent.STOP_DRAWING, true, true, mouseX, mouseY);
        dispatchEvent(e);
        if (!e.isDefaultPrevented()){
            inactivate();
            activate();
            if (_currentTool){
                stack(_currentTool.displayObject);
                _currentTool.stop(mouseX, mouseY);
            }
        }
    }
}


import flash.events.Event;

/**
 * drawing event
 * @author naoto koshikawa
 */
class DrawingEvent extends Event {
    public static const START_DRAWING:String = "startDrawing";
    public static const MOVE_DRAWING:String = "moveDrawing";
    public static const STOP_DRAWING:String = "stopDrawing";
    
    private var _x:Number;
    public function get x():Number{
        return _x;
    }
    
    private var _y:Number;
    public function get y():Number{
        return _y;
    }
    
    public function DrawingEvent(type:String, bubbles:Boolean=false,
                                cancelable:Boolean=false, x:Number = 0, y:Number = 0){ 
        super(type, bubbles, cancelable);
        _x = x;
        _y = y;
    } 
    
    public override function clone():Event{ 
        return new DrawingEvent(type, bubbles, cancelable, _x, _y);
    } 
    
    public override function toString():String { 
        return formatToString("DrawingEvent", "type", "bubbles", "cancelable", "eventPhase", "x", "y"); 
    }
    
}

import flash.display.DisplayObject;

/**
 * jp.ppworks.drawing.simple
 * パッケージで使用できるツールのインターフェースです
 * 
 * @author naoto koshikawa
 */
interface ITool {
    function get displayObject():DisplayObject;
    function set options(options:Object):void;
    function get options():Object;
    function start(x:Number, y:Number):void;
    function move(x:Number, y:Number):void;
    function stop(x:Number, y:Number):void;
}

import flash.display.*;

/**
 * Pen Tool
 * @author naoto koshikawa
 */
class PenTool implements ITool{
    private var _displayObject:Shape;
    public function get displayObject():DisplayObject {
        return _displayObject;
    }
    
    private var _options:Object;
    public function get options():Object {
        return _options;
    }
    
    public function set options(opt:Object):void {
        if (opt && opt.thickness) _options.thickness = opt.thickness;
        if (opt && opt.color) _options.color = opt.color;
        if (opt && opt.alpha) _options.alpha = opt.alpha;
    }
    
    // _____________________________________________________ Method
    public function PenTool(){
        _options = {
            thickness:3,
            color:0x000000,
            alpha:0
        };
    }
    
    public function start(x:Number, y:Number):void {
        _displayObject = new Shape();
        _displayObject.graphics.lineStyle(
            _options.thickness,
            _options.color,
            _options.alpha
        );
        _displayObject.graphics.moveTo(x, y);
    }
    
    public function move(x:Number, y:Number):void {
        if (!_displayObject) return;
        _displayObject.graphics.lineTo(x, y);
    }
    
    public function stop(x:Number, y:Number):void {
        if (!_displayObject) return;
        if (_displayObject.width == _options.thickness
            && _displayObject.height == _options.thickness) {
            _displayObject.graphics.clear();
            _displayObject.graphics.beginFill(_options.color,_options.alpha);
            _displayObject.graphics.drawCircle(x, y, _options.thickness/2);
        }
        else {
            move(x, y);
        }
    }
}


import flash.display.*;
import flash.events.*;
import flash.geom.Point;

class BrushTool implements ITool{
    
    private var _displayObject:Shape;
    public function get displayObject():DisplayObject {
        return _displayObject;
    }
    
    private var _options:Object;
    public function get options():Object {
        return _options;
    }
    
    public function set options(opt:Object):void {
        if (opt && opt.thickness) _options.thickness = opt.thickness;
        if (opt && opt.color) _options.color = opt.color;
        if (opt && opt.alpha) _options.alpha = opt.alpha;
    }
    
       
    // _____________________________________________________ Method
    public function BrushTool(){
        _options = {
            thickness:3,
            color:0x000000,
            alpha:0.0
        };
    }
    
    public function start(x:Number, y:Number):void {
        _displayObject = new Shape();
        ps = new Array();
        _displayObject.graphics.lineStyle(
            _options.thickness,
            _options.color
        );
        _displayObject.graphics.moveTo(x, y);
    }
    
    public function move(x:Number, y:Number):void {
        if (!_displayObject) return;
        var p:Point = new Point(x, y);//カーソル座標
        ps.push(p);
        draw();
    }
    
    public function stop(x:Number, y:Number):void {
        if (!_displayObject) return;
        if (_displayObject.width == _options.thickness
            && _displayObject.height == _options.thickness) {
            _displayObject.graphics.clear();
            _displayObject.graphics.beginFill(_options.color);
            _displayObject.graphics.drawCircle(x, y, _options.thickness/2);
        }
        else {
            move(x, y);
        }
    }
    
    // ____
        private var ps:Array = [];//座標点配列
        private var smoothLength:int = 4;
       // private var halfPenWidth:Number =  20;//線の太さ

        //描画処理
        private function draw():void{
            
            var cx:Number;
            var cy:Number;
                   
            var tx:Number;
            var ty:Number;
                    
            var a:Number;
                    
            var dx:Number;
            var dy:Number;
                    
            var cx0:Number;
            var cx1:Number;
                    
            var cy0:Number;
            var cy1:Number;
                    
            var tx0:Number;
            var tx1:Number;
                    
            var ty0:Number;
            var ty1:Number;
            
            with(_displayObject){
                graphics.clear();
                graphics.lineStyle(1, _options.color,_options.alpha/2);
                graphics.beginFill( _options.color,_options.alpha);
            }

            
            
            if (ps.length > 1){
                var lx0:Number = ps[0].x / 2 + ps[1].x / 2;
                var ly0:Number = ps[0].y / 2 + ps[1].y / 2;
                var lx1:Number = lx0;
                var ly1:Number = ly0;
                _displayObject.graphics.moveTo(tx, ty);
            }
            var i:int = 0;
            
            for (i = 0; i < ps.length - 2; i++ ){
                var length:Number = Point.distance(ps[i], ps[i + 1]);
                if (length > smoothLength) {
                    //_displayObject.graphics.beginFill( _options.color,_options.alpha);
                    cx = ps[i].x;
                    cy = ps[i].y;
                    
                    tx = ps[i].x / 2 + ps[i + 1].x / 2;
                    ty = ps[i].y / 2 + ps[i + 1].y / 2;
                    
                    a = Math.atan2(ty - cy, tx - cx);
                    
                    dx = Math.sin(a - Math.PI / 2) * _options.thickness/length;
                    dy = Math.cos(a - Math.PI / 2) * _options.thickness/length;
                    
                    cx0 = cx + dx;
                    cx1 = cx - dx;
                    
                    cy0 = cy + dy;
                    cy1 = cy - dy;
                    
                    tx0 = tx + dx;
                    tx1 = tx - dx;
                    
                    ty0 = ty + dy;
                    ty1 = ty - dy;
                    if(i<smoothLength)continue;
                    with(_displayObject){
                        graphics.moveTo(lx0, ly0);
                        graphics.curveTo(cx0, cy0 , tx0 , ty0 );
                        graphics.lineTo(tx1, ty1);
                        graphics.curveTo(cx1, cy1, lx1, ly1);
                        graphics.lineTo(lx0, ly0);
                    }

                    
                    
                    lx0 = tx0;
                    ly0 = ty0;
                    lx1 = tx1;
                    ly1 = ty1;
                    //_displayObject.graphics.endFill()
                }
            }
            
            
            
            if (ps.length > smoothLength) {
                cx = ps[i].x;
                cy = ps[i].y;
                tx = ps[i].x / 2 + ps[i + 1].x / 2;
                ty = ps[i].y / 2 + ps[i + 1].y / 2;
                
                a = Math.atan2(ty - cy, tx - cx);
                
                cx0 = cx + dx;
                cx1 = cx - dx;
                cy0 = cy + dy;
                cy1 = cy - dy;
                with(_displayObject){
                    graphics.moveTo(lx0, ly0);
                    graphics.curveTo(cx0, cy0 , tx , ty );
                    graphics.curveTo(cx1, cy1, lx1, ly1);
                    graphics.lineTo(lx0, ly0);
                }

                
            }
            
        }
    }