/**
* 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);
}
}
}
}