In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Paint Tool + Spline

TwitPaintが納得いかないので自分で作ってみる。

線の描画をカーブにしてみた。まだがくがくする。
取得する座標が近すぎるのかな。
Get Adobe Flash player
by whirlpower 21 Sep 2010
/**
 * TwitPaintが納得いかないので自分で作ってみる。
 * 
 * 線の描画をカーブにしてみた。まだがくがくする。
 * 取得する座標が近すぎるのかな。
 * 
 */
package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    
    public class Main extends Sprite 
    {
        
        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point
            
            addChild( new PaintTool() );
        }
    }    
}

    import com.bit101.components.Label;
    import com.bit101.components.PushButton;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.ui.Mouse;
    
    /**
    * ペイントツール本体
    */
    internal class PaintTool extends Sprite
    {
        private var _data : ToolData;
        private var _canvas : Canvas;
        private var _backgroud : Shape;
        private var _cursor : Cursor;
        private var _colorButtons : Array;
        private var _brushButtons : Array;
        
        public function PaintTool()
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
            
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            
            // ツールデータの作成
            _data = new ToolData();
            
            // 背景の作成
            _backgroud = new Shape();
            _backgroud.graphics.beginFill( 0xEEEEEE, 1 );
            _backgroud.graphics.drawRect( 0, 0, stage.stageWidth, stage.stageHeight );
            _backgroud.graphics.endFill();
            addChild( _backgroud );
            
            // キャンバスの作成
            _canvas = new Canvas( this, _data  );
            addChild( _canvas );
            
            stage.addEventListener( MouseEvent.MOUSE_MOVE, stageMouseMoveHandler );
            
            _canvas.addEventListener( MouseEvent.MOUSE_MOVE, mouseMoveHandler );
            _canvas.addEventListener( MouseEvent.MOUSE_DOWN, mouseDownHandler );
            _canvas.addEventListener( MouseEvent.MOUSE_UP, mouseUpHandler );
            _canvas.addEventListener( MouseEvent.MOUSE_OVER, mouseOverHandler );
            _canvas.addEventListener( MouseEvent.MOUSE_OUT, mouseOutHandler );
            
            
            // カラーボタンの作成
            var posY : int = _canvas.height + 15;
            var posX : int = 115;
            
            var colorLabel : Label = new Label( this, 32, posY-8, "COLOR" );
            
            _colorButtons = new Array();
            var colors : Array = [ 
                0xA40000, 0xE95505, 0xFFF100, 0x8FC31F,
                0x007130, 0x00A0E9, 0x00479B, 0xEB6877,
                0x601986, 0x6A3906, 0xF8B551, 0x1B1B1B,
                0x898989, 0xB5B5B5, 0xFFFFFF
            ];
            
            for each( var c:uint in colors ) 
            {
                var colorButton : ColorButton = new ColorButton( c ); 
                colorButton.addEventListener( MouseEvent.CLICK, changeColor );
                colorButton.x = posX;
                colorButton.y = posY;
                posX += 22;
                
                colorButton.addEventListener( MouseEvent.MOUSE_OVER, palletMouseOverHandler );
                colorButton.addEventListener( MouseEvent.MOUSE_OUT, palletMouseOutHandler );
                
                _colorButtons.push( colorButton );
                addChild( colorButton );
            }
            
            // ブラシサイズ変更ボタンの作成
            posY = _canvas.height + 45;
            posX = 115;
            
            var radiusLabel : Label = new Label( this, 32, posY-8, "BRUSH SIZE" );
            
            _brushButtons = new Array();
            var brushs : Array = [ 1, 2, 3, 5, 7, 9, 12, 15 ];
            
            for each( var b:uint in brushs ) 
            {
                var brushButton : RadiusButton = new RadiusButton( b ); 
                brushButton.addEventListener( MouseEvent.CLICK, changeRadius );
                brushButton.x = posX;
                brushButton.y = posY;
                posX += 22;
                
                brushButton.addEventListener( MouseEvent.MOUSE_OVER, palletMouseOverHandler );
                brushButton.addEventListener( MouseEvent.MOUSE_OUT, palletMouseOutHandler );
            
                _brushButtons.push( brushButton );
                addChild( brushButton );
            }
            
            posY = _canvas.height + 70;
            posX = 105;
            
            // すべて消去ボタン
            new PushButton( this, posX, posY, "undo", undo );
            
            // アンドゥ
            new PushButton( this, posX + 110, posY, "All clear", fillAll );
            
            // カーソルの作成
            _cursor = new Cursor( _data );
            addChild( _cursor );
        }
        
        /**
         * キャンバス内でのマウスイベント
         */
        private var _mouseDown : Boolean = false;
        private function mouseDownHandler(e:MouseEvent):void 
        {
            _mouseDown = true;
            _canvas.startStroke( mouseX, mouseY );
        }
        
        private function mouseUpHandler(e:MouseEvent):void 
        {
            _mouseDown = false;
            _canvas.endStroke();
        }
        
        private function mouseOverHandler(e:MouseEvent):void 
        {
            _cursor.change( Cursor.PAINT );
        }
        
        private function mouseOutHandler(e:MouseEvent):void 
        {
            _cursor.change( "normal" );
            
            if ( _mouseDown )
            {
                _mouseDown = false;
                _canvas.endStroke();
            }
        }
        
        private function mouseMoveHandler(e:MouseEvent):void 
        {
            if( _mouseDown )
            {
                _canvas.drawStroke( mouseX , mouseY );
            }
        }
        
        /**
         * パレットエリアのマウスイベント
         * @param    e
         */
        private function palletMouseOverHandler(e:MouseEvent):void 
        {
            _cursor.change( Cursor.SPOIT );
        }
        
        private function palletMouseOutHandler(e:MouseEvent):void 
        {
            _cursor.change( "normal" );
        }
        
        /**
         * ステージ内でのマウスイベント
         * @param    e
         */
        private function stageMouseMoveHandler(e:MouseEvent):void 
        {
            _cursor.x = this.mouseX;
            _cursor.y = this.mouseY;
        }
        
        /**
         * ペンの太さを変更する。
         * @param    e
         */
        private function changeRadius( e:Event ):void
        {
            _data.radius = e.target.radius;
            _cursor.change( Cursor.SPOIT );
        }
        
        /**
         * 色を変更する。
         * @param    e
         */
        private function changeColor( e:Event ):void
        {
            _data.color = e.target.color;
            _cursor.change( Cursor.SPOIT );
        }
        
        /**
         * 全部消す
         * @param    e
         */
        private function fillAll( e:Event ):void
        {
            _canvas.fillAll( 0xFFFFFF );
            _data.lines = new Vector.<Stroke>();            
        }
        
        /**
         * 一筆もどる
         * @param    e
         */
        private function undo( e:Event ):void
        {
            _data.lines.pop();
            _canvas.reDraw();
        }
    }
    
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Graphics;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.geom.Matrix;
    
    /**
    * 描画領域
    */
    internal class Canvas extends Sprite
    {
        private var _bitmapData : BitmapData;
        private var _container : Sprite;
        private var _data : ToolData;
        private var _posX : int = 0;
        private var _posY : int = 0;
        private var _stroke : Stroke;
        
        private var _canvasX : int = 32; 
        private var _canvasY : int = 32;
        private var _canvasW : int = 400;
        private var _canvasH : int = 300;
        
        public function Canvas( container:Sprite, data:ToolData ):void
        {
            _container = container;
            _data = data;
            
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
            
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            
            _bitmapData = new BitmapData( _canvasW, _canvasH, true, 0xFFFFFFFF );
            var bitmap : Bitmap = new Bitmap( _bitmapData );
            bitmap.x = _canvasX;
            bitmap.y = _canvasY;
            addChild( bitmap );
            
            // キャンバス有効面の作成
            graphics.beginFill( 0xDDDDDD, 1 );
            graphics.drawRect( 0, 0, stage.stageWidth, _canvasH + _canvasY*2 );
            graphics.endFill();
        }
        
        /**
         * 描き始めのポイントをセットする。
         * @param    posX
         * @param    posY
         */
        public function startStroke( posX:Number, posY:Number ):void
        {
            _posX = posX;
            _posY = posY;
            
            _stroke = new Stroke( _data.color, _data.radius );
            _container.addChild( _stroke.shape );
            _stroke.shape.x = this.x;
            _stroke.shape.y = this.y;
            _stroke.stroke.push( posX, posY );
            drawLine();
        }
        
        /**
         * 線を追加する
         * @param    posX
         * @param    posY
         */
        public function drawStroke( posX:Number, posY:Number ):void
        {
            _stroke.stroke.push( posX, posY );
            drawLine();
        }
        
        /**
         * 描きおわり
         */
        public function endStroke():void
        {
            if ( _stroke )
            {
                _container.removeChild( _stroke.shape );
                _data.lines.push( _stroke );
                bake();
                _stroke = null;
            }
        }
        
        /**
         * ストロークをbitmapDataに焼きこむ
         */
        public function bake():void
        {
            _bitmapData.lock();
            _bitmapData.draw( _stroke.shape, new Matrix( 1, 0, 0, 1, -_canvasX, -_canvasY ) );
            _bitmapData.unlock();            
        }
        
        /**
         * キャンバスに書き込む
         * @param    posX
         * @param    posY
         */
        public function draw( posX:int, posY:int ):void
        {
            var line : Shape = new Shape();
            var g : Graphics = line.graphics;
            
            var xc:Number = ( _posX + posX ) / 2;
            var yc:Number = ( _posY + posY ) / 2;
            
            g.lineStyle( _data.radius, _data.color, 1 );
            g.moveTo( _posX, _posY );
            g.curveTo( posX, posY, xc, yc );
            
            _stroke.stroke.push( posX, posY );
            
            _posX = posX;
            _posY = posY;
            
            _bitmapData.lock();
            _bitmapData.draw( line );
            _bitmapData.unlock();
        }
        
        /**
         * 一筆の描画
         */
        private function drawLine():void
        {
            var stroke : Vector.<int> = _stroke.stroke;
            var leng : int = stroke.length;
            var g : Graphics = _stroke.shape.graphics;
            
            _stroke.shape.graphics.clear();
            g.moveTo( stroke[0], stroke[1] );
            for ( var i :int = 0; i < leng-2; i+=2 )
            {
                var xc:Number = ( stroke[i  ] + stroke[i + 2] ) / 2;
                var yc:Number = ( stroke[i+1] + stroke[i + 3] ) / 2;
                
                g.lineStyle( _stroke.radius, _stroke.color, 1 );
                g.curveTo( stroke[i], stroke[i+1], xc, yc );
            }
        }    

        /**
         * 描画記録から描画をしなおす。
         */
        public function reDraw():void
        {
            fillAll( 0xFFFFFF );
            
            if ( _data.lines.length == 0 ) return;
            
            var lines : Vector.<Stroke> = _data.lines;
            var l : int = lines.length;
            for ( var j:int = 0; j < l; j++ )
            {
                _stroke = lines[j];
                bake();
            }
        }
        
        /**
        * すべてを消す
        */
        public function fillAll( color:uint ):void
        {
            _bitmapData.fillRect( _bitmapData.rect, color + 0xFF000000 );
        }
    }
    
    /**
    * キャンバス上で扱うデータ
    */
    internal class ToolData
    {
        // position, color, radius
        public var lines : Vector.<Stroke> = new Vector.<Stroke>();
        public var color : uint = 0x00479B;
        public var radius : Number = 4;
    }
    
    import flash.display.Shape;
    
    /**
     * 一筆のデータ
     */
    internal class Stroke
    {
        public var stroke : Vector.<int> = new Vector.<int>;
        public var color : uint;
        public var radius : int;
        public var shape : Shape;
        
        public function Stroke( color:uint, radius:int ):void
        {
            this.radius = radius;
            this.color = color;
            this.stroke = new Vector.<int>;
            this.shape = new Shape();
        }
    }
    
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    
    /**
     * パレットで使うボタンのスーパークラス
     */
     class PalletButton extends Sprite
    {
        public function PalletButton():void
        {
            addEventListener( MouseEvent.MOUSE_DOWN, mouseDownHandler );
            addEventListener( MouseEvent.MOUSE_UP, mouseUpHandler );
            addEventListener( MouseEvent.MOUSE_OVER, mouseOverHandler );
            addEventListener( MouseEvent.MOUSE_OUT, mouseOutHandler );
        }
        
        private function mouseDownHandler(e:MouseEvent):void 
        {
        }
        
        private function mouseUpHandler(e:MouseEvent):void 
        {
        }
        
        private function mouseOverHandler(e:MouseEvent):void 
        {
            scaleX = 1.2;
            scaleY = 1.2;
        }
        
        private function mouseOutHandler(e:MouseEvent):void 
        {
            scaleX = 1;
            scaleY = 1;
        }
    }
    
    import flash.display.Sprite;
    
    /**
     * カラー変更ボタン
     */
    internal class ColorButton extends PalletButton
    {
        public var color :uint;
        
        private var _size : int = 20;
        
        public function ColorButton( color:uint ):void
        {
            super();
            
            this.color = color;
            
            graphics.beginFill( color, 1 );
            graphics.drawRect( -_size/2, -_size/2, _size, _size );
            graphics.endFill();
            graphics.lineStyle( 0.5, 0x888888, 1 );
            graphics.drawRect( -_size/2, -_size/2, _size, _size );
            
            buttonMode = true;
        }
    }
    
    import flash.display.Sprite;
    
    /**
     * ペンの太さ変更ボタン
     */
    internal class RadiusButton extends PalletButton
    {
        public var radius :uint = 1;
        
        private var _size : int = 20;
        
        public function RadiusButton( radius:uint ):void
        {
            super();
            
            this.radius = radius;
            
            graphics.beginFill( 0xFFFFFF, 1 );
            graphics.drawRect( -_size/2, -_size/2, _size, _size );
            graphics.endFill();
            
            graphics.beginFill( 0x000000, 1 );
            graphics.drawCircle( 0, 0, radius/2 );
            graphics.endFill();
            
            graphics.lineStyle( 0.5, 0x888888, 1 );
            graphics.drawRect( -_size/2, -_size/2, _size, _size );
            
            buttonMode = true;
        }
    }
    
    import flash.display.Sprite;
    import flash.ui.Mouse;
    
    /**
     * カーソル
     */
    internal class Cursor extends Sprite
    {
        private var _toolData : ToolData;
        
        public static const PAINT : String = "paint";
        public static const SPOIT : String = "spoit";
        
        public function Cursor( data:ToolData ):void
        {
            this._toolData = data;
            
            mouseEnabled = false;
            mouseChildren = false;
        }
        
        /**
         * 再描画する。
         */
        public function change( mode:String ):void
        {
            if ( PAINT == mode )
            {
                paintMode();
            }
            else if ( SPOIT == mode )
            {
                spoitMode();
            }
            else
            {
                normal();
            }
        }
        
        private function normal():void
        {
            graphics.clear();
            Mouse.show();
        }
        
        /**
         * キャンバス上でのカーソル
         */
        private function paintMode():void
        {
            graphics.clear();
            Mouse.hide();
            
            if ( _toolData.radius < 3 )
            {
                graphics.beginFill( _toolData.color, 1 );
                graphics.drawCircle( 0, 0, _toolData.radius/2 );
                graphics.endFill();
                
                graphics.lineStyle( 0.5, 0x555555, 0.5 );
                graphics.moveTo( -15, 0.5 );
                graphics.lineTo( -10, 0.5 );
                graphics.moveTo(  15, 0.5 );
                graphics.lineTo(  10, 0.5 );
                graphics.moveTo( 0.5, -15 );
                graphics.lineTo( 0.5, -10 );
                graphics.moveTo( 0.5,  15 );
                graphics.lineTo( 0.5,  10 );
                
            }
            else
            {
                graphics.lineStyle( 0.5, 0x555555, 0.5 );
                graphics.beginFill( _toolData.color, 1 );
                graphics.drawCircle( 0, 0, _toolData.radius/2 );
                graphics.endFill();
            }
        }
        
        /**
         * カラー、ブラシ上でのカーソル
         */
        private function spoitMode():void
        {
            graphics.clear();
            Mouse.hide();
            
            
            graphics.beginFill( 0x555555, 1 );
            graphics.moveTo(  0,  0 );
            graphics.lineTo( 20, 10 );
            graphics.lineTo( 10, 20 );
            graphics.lineTo(  0,  0 );
            
            graphics.beginFill( 0xFFFFFF, 1 );
            graphics.drawCircle( 20, 20, 10 );
            graphics.endFill();
            
            graphics.beginFill( _toolData.color, 1 );
            graphics.drawCircle( 20, 20, _toolData.radius/2 );
            graphics.endFill();
            
            graphics.lineStyle( 0.5, 0x555555, 1 );
            graphics.drawCircle( 20, 20, 10 );
            
        }
        
    }