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

ブラシの入りと抜き

マウスやペンタブレットで線を書きます。
ブラシの「入り」と「抜き」の表現のテストです
Get Adobe Flash player
by misinoe 30 Oct 2013
    Embed
/**
 * Copyright misinoe ( http://wonderfl.net/user/misinoe )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/3xRL
 */

/**
    *
    * マウスやペンタブレットで線を書きます。
    * ブラシの「入り」と「抜き」の表現のテストです
    *
    */
package {
    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.events.MouseEvent;
    import flash.events.Event;
    import flash.geom.Point;
    
    //
    public class FlashTest extends Sprite {
        
        // ブラシインスタンス
        private var brush:Brush;
        
        // デバッグ関連のプロパティ
        private var debugLog:Array/* of String */ = [];
        private var debugField:TextField;
        
        // コンストラクタ
        public function FlashTest() {
            // write as3 code here..
            
            // デバッグログを作成
            debugField = new TextField();
            debugField.selectable = false;
            debugField.width = 200;
            debugField.height = 400;
            addChild( debugField );
            
            // マウスダウン
            // mouseDownHandler → mouseMoveHandlerとenterFrameHandler → mouseUpHandler
            // の流れで処理が推移していきます。
            stage.addEventListener( MouseEvent.MOUSE_DOWN, mouseDownHandler );
        }
        
        /**
        * 引数をデバッグログに追加し表示します
        * 20を超えたら先頭から削除していきます。
        */
        private function log(...args):void{
            debugLog.unshift( args );
            if( debugLog.length > 20 ) debugLog.pop();
            debugField.text = debugLog.join("\n");
        }
        
        
        
        
        
        /**
        * ステージのマウスが押下された時のイベントハンドラーです。
        * リスナーの登録と、線の描画の開始をトリガーします。
        */
        private function mouseDownHandler( event:MouseEvent ):void{
            // リスナー登録処理
            stage.addEventListener( MouseEvent.MOUSE_MOVE, mouseMoveHandler);
            stage.addEventListener( Event.ENTER_FRAME, enterFrameHandler);
            stage.addEventListener( MouseEvent.MOUSE_UP, mouseUpHandler);
            // スプライトを作成
            var sprite:Sprite = new Sprite();
            addChild( sprite );
            // ブラシを作成
            brush = new Brush( sprite.graphics );
            brush.brushStyle( 0xFFFFFF*Math.random(), Math.random() );
            // 線の始点
            brush.strokeFirstPoint( new Point( mouseX,mouseY ) );
        }
        
        /**
        * ステージのマウス移動用のイベントハンドラーです。
        * updateAfterEventを行い、高周波の表示更新でユーザーにフィードバックします
        */
        private function mouseMoveHandler( event:MouseEvent ):void{
            
            brush.strokeUpdatePoint( new Point(mouseX,mouseY) );
            event.updateAfterEvent();
        }
        /**
        * エンターフレームイベント。マウスムーブとは別にポインティグのアップデートを行います。
        */
        private function enterFrameHandler( event:Event ):void{
            brush.strokeUpdatePoint( new Point(mouseX,mouseY) );
        }
        
        /**
        * ステージのマウスアップ。登録したリスナーを消去します
        */
        private function mouseUpHandler( event:MouseEvent ):void{
            
            stage.removeEventListener( MouseEvent.MOUSE_MOVE, mouseMoveHandler);
            stage.removeEventListener( MouseEvent.MOUSE_UP, mouseUpHandler);
            stage.removeEventListener( Event.ENTER_FRAME, enterFrameHandler);
            
            brush.graphics.clear();
            Brush.drawStroke( brush.graphics, brush.brushColor, brush.brushAlpha, brush.strokePoints, brush.strokeDistance );
        }
    }
}

import flash.display.Graphics;
import flash.geom.Point;

internal class Brush{
    
    
    /**
    * ストロークの情報等を元に一括描画を行います
    * @param graphics:Graphics 描画対象のグラフィックス
    * @param col:uint 描画色 0x000000~0xFFFFFF
    * @param alpha:Number 不透明度 0~1
    * @param strokes:Array of Point flash.geom.Pointが入った配列
    * @param totalStroke:Number strokesで設定した線の総延長
    * @param strokeIn:Number=200.0 入りの距離
    * @param strokeOut:Number=200.0 抜きの距離
    * @param brushMin:Number=1.0 入り抜きで使われるブラシの最小の太さ
    * @param brushMax:Number=6.0 入り抜きの範囲外のブラシの最大
    */
    static public function drawStroke( graphics:Graphics, col:uint, alpha:Number, strokes:Array/* of Point*/, totalStroke:Number, strokeIn:Number=200.0, strokeOut:Number=200.0, brushMin:Number=1.0, brushMax:Number=6.0 ):void{
        // ストローク情報をコピー
        strokes = strokes.concat([]);
        
        var brush:Brush = new Brush( graphics );
        brush.brushStyle( col, alpha );
        brush.strokeTotalDistance = totalStroke;
        brush.strokeIn = strokeIn;
        brush.strokeOut = strokeOut;
        brush.brushMin = brushMin;
        brush.brushMax = brushMax;
        // 始点
        var point:Point = strokes.shift();
        brush.strokeFirstPoint( point );
        // 次の点以降
        while( strokes.length ){
            point = strokes.shift();
            brush.strokeUpdatePoint( point );
        }
        
    };
    
    
    //
    public var graphics:Graphics;
    
    // 描画に関係するプロパティ
    public var strokePoints:Array/* of Point */    // ストロークのポイント
    public var strokeDistance:Number = 0.0;    // 現在描画中のストロークの長さ
    private var strokeLastPoint:Point = null;    // 直前の座標
    private var strokeLastSize:Number = 0.0;    // 直前の太さ
    private var strokeLastRPPI:Number = 0.0;    // 直前の角度( RadianPerPI );
    
    public var strokeTotalDistance:Number = -1.0;    // 線の総延長が判明している場合に設定します
    public var strokeIn:Number = 200.0;    // 入りを何ピクセルまで行うかを指定します
    public var strokeOut:Number = 200.0;    // 最後の何ピクセルからを抜きにするかを指定します
    
    public var brushMin:Number = 1.0;    // ブラシの最小サイズ
    public var brushMax:Number = 6.0;    // ブラシの最大サイズ
    
    public var brushColor:uint = 0x000000;
    public var brushAlpha:Number = 0.0;


    // コンストラクタ
    public function Brush( graphics:Graphics ):void{
        this.graphics = graphics;
    }
    
    // ブラシのスタイルを設定する
    public function brushStyle( color:uint, alpha:Number=0 ):void{
        brushColor = color;
        brushAlpha = alpha;
    }
    
    /**
    * 始点
    * @param point:Point
    */
    public function strokeFirstPoint( point:Point ):void{
        strokeLastPoint = point;
        strokePoints = [point];
        strokeDistance = 0;
        strokeLastRPPI = NaN;
        strokeLastSize = 0;
            
        // graphics.moveTo( point.x, point.y );
    }
        
        
    /**
    * 次のポイント
    * @param point:Point
    */
    public function strokeUpdatePoint( point:Point ):void{
       
       // 直前の点との距離
       var dis:Number = Point.distance( point, strokeLastPoint );
       if( dis <= 2 ) return;
       strokeDistance += dis;
            
       // 直前の点との角度
       var radPerPI:Number = Math.atan2( point.y-strokeLastPoint.y, point.x-strokeLastPoint.x ) / Math.PI;
       if( isNaN(strokeLastRPPI) ) strokeLastRPPI = radPerPI;
            
       // サイズの計算
       var size:Number = brushMax;
       // ブラシの入り
       if( strokeDistance < strokeIn ){
           size = (size-brushMin)*(strokeDistance/strokeIn) + brushMin;
       }else if( strokeTotalDistance>0 && strokeDistance > strokeTotalDistance-strokeOut ){
           size =  ( (size-brushMin)* ((strokeTotalDistance-strokeDistance)/strokeOut)) + brushMin;
       }
       size += (size-strokeLastSize)*0.3;
       
            
       // 台形の角度
       var r1:Number = (strokeLastRPPI - 0.5)*Math.PI;
       var r2:Number = (radPerPI - 0.5)*Math.PI;
       var r3:Number = (radPerPI + 0.5)*Math.PI;
       var r4:Number = (strokeLastRPPI + 0.5)*Math.PI;
            
       // 台形を描画
       graphics.moveTo( strokeLastPoint.x+Math.cos(r1)*strokeLastSize, strokeLastPoint.y+Math.sin(r1)*strokeLastSize );
       graphics.beginFill( brushColor, brushAlpha );
       graphics.lineTo( point.x+Math.cos(r2)*size, point.y+Math.sin(r2)*size );
       graphics.lineTo( point.x+Math.cos(r3)*size, point.y+Math.sin(r3)*size );
       graphics.lineTo( strokeLastPoint.x+Math.cos(r4)*strokeLastSize, strokeLastPoint.y+Math.sin(r4)*strokeLastSize );
       graphics.endFill();
       
       // 次回サイクルする際に使用する変数の引き継ぎ
       strokeLastRPPI = radPerPI;
       strokeLastPoint= point;
       strokeLastSize = size;
       
       strokePoints.push( point );
           
     }
}