ブラシの入りと抜き
マウスやペンタブレットで線を書きます。
ブラシの「入り」と「抜き」の表現のテストです
/**
* 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 );
}
}