package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
/**
書道クラス
*/
public class Shodo extends Sprite
{
//半紙
private var paper:Sprite;
//一つ前の座標
private var oldX1:Number;
private var oldY1:Number;
//二つ前の座標
private var oldX2:Number;
private var oldY2:Number;
//一つ前の幅
private var oldW:Number;
//筆の太さ
private var strength:Number = 20;
//筆の太さの幅(太さ-太さの幅=最小の太さ)
private var range:Number = 12;
//筆の変化幅
private var limitDistance:Number = 30;
public function Shodo(w:Number = 100,h:Number = 100)
{
initPaper(w,h);
}
// **************************************** 表示領域の初期化
private function initPaper(w,h):void
{
//半紙を配置する
paper = new Sprite();
addChild(paper);
paper.graphics.beginFill(0xffffff);
paper.graphics.drawRect(0, 0, w, h);
//マウスが半紙上で押されるのを検知
paper.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
}
// **************************************** マウスが押された。
private function mouseDownHandler(e:MouseEvent):void
{
//マウスの動きを検知
addEventListener(MouseEvent.MOUSE_MOVE,mouseMoveHandler)
//ステージにマウスボタンが離されるリスナーを配置
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
//筆を置いたときのイメージを置いた座標に配置
var hajime:Hajime = new Hajime();
hajime.x = paper.mouseX;
hajime.y = paper.mouseY;
paper.addChild(hajime);
//座標の履歴をとりあえず格納
oldX1 = paper.mouseX;
oldY1 = paper.mouseY;
oldX2 = paper.mouseX;
oldY2 = paper.mouseY;
oldW = strength;
}
// **************************************** マウスが離された。
private function mouseUpHandler(e:MouseEvent):void
{
//リスナーを削除
removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler)
//前座標と前々座標の距離、角度、拡大率を求める。
var distance:Number = Math.sqrt((oldX1 - oldX2) * (oldX1 - oldX2) + (oldY1 - oldY2) * (oldY1 - oldY2));
var deg:Number = Math.atan2(oldY1 - oldY2, oldX1 - oldX2) * 180 / Math.PI;
var scale:Number = oldW / strength;
//マウスボタンを離す前の2座標の距離に応じて、トメやハライのイメージを配置する。
var postfix:Sprite;
if (distance > 25) {
postfix = new Harai();
} else if (distance > 10) {
postfix = new Hane();
} else {
postfix = new Tome();
}
postfix.x = oldX1;
postfix.y = oldY1;
postfix.scaleX = postfix.scaleY = scale;
postfix.rotation = deg;
paper.addChild(postfix);
}
// **************************************** マウスが動いた
private function mouseMoveHandler(e:MouseEvent):void
{
//前座標との距離、角度を求める。幅wも適当に求める。(変化幅以上に移動していたら最大細さ。それ以内はそれに比例した細さ。)
var distance:Number = Math.sqrt((paper.mouseX - oldX1) * (paper.mouseX - oldX1) + (paper.mouseY - oldY1) * (paper.mouseY - oldY1));
var w:Number = distance > limitDistance?(strength - range):(strength - range * distance / limitDistance);
var deg:Number = Math.atan2(paper.mouseY - oldY1, paper.mouseX - oldX1) * 180 / Math.PI;
//原点に下底前幅、上底現幅、高さ現距離の台形を描き(エルボーとして前幅の円も原点に配置)、
var s:Sprite = new Sprite();
s.graphics.beginFill(0, 1);
s.graphics.drawCircle(0, 0, oldW / 2);
s.graphics.endFill()
s.graphics.beginFill(0, 1);
s.graphics.moveTo(0, -oldW / 2)
s.graphics.lineTo(distance, -w / 2);
s.graphics.lineTo(distance, w / 2);
s.graphics.lineTo(0, oldW / 2);
s.graphics.lineTo(0, -oldW / 2)
s.graphics.endFill()
//前座標に求めた角度に回転させて配置する。
s.rotation = deg;
s.x = oldX1;
s.y = oldY1;
paper.addChild(s);
//履歴を格納
oldX2 = oldX1;
oldY2 = oldY1;
oldX1 = paper.mouseX;
oldY1 = paper.mouseY;
oldW = w;
}
// **************************************** 半紙クリアのメソッド
public function clearPaper() {
for (var i:int = paper.numChildren; i > 0; i--)
{
paper.removeChildAt(i - 1);
}
}
}
}
使い方は
//Shodoを作成
shodo = new Shodo(480,330);
addChild(shodo);
//枠を描く
var f:Sprite = new Sprite();
f.graphics.lineStyle(0,0x666666);
f.graphics.drawRect(0,0,480,330);
addChild(f);
//ボタンを配置
var clearBtn:Button = new Button()
clearBtn.y = 336;
clearBtn.label = 'clear';
clearBtn.addEventListener(MouseEvent.CLICK,onClickHandler)
addChild(clearBtn);
function onClickHandler(e:MouseEvent):void {
shodo.clearPaper();
}
こんな感じです。筆圧感知ができないと思うので(マウスが前提ですし...)移動した距離によって(すなわちマウスの速さによって)線の太さを決めています。早く動かすと細くなるイメージで、そこは適当に計算して決めています。
イメージだけのクラスの作成に悩んでしまったので、トメ、ハネ、ハライ、ハジメのイメージはFLA内でそれぞれTome,Hane,Harai,Hajimeの名前でActionScriptに書き出ししています。
Your publishis an inspiration for me to study more about this topic. I must concede your lucidity widened my views and I will forthwith snatch your rss feed to remain up to date on any incoming articles you might publish.