Aswing "Drawing board"

本文介绍如何使用AsWing框架实现一个简单的涂鸦板应用,包括捕捉鼠标事件完成绘图、添加‘撤销’功能及鼠标离开时的模糊效果。

This is drawing board.

下面学习如何捕捉鼠标事件、键盘事件和焦点事件。

 

在AsWing当中的组件都是Sprite的子类,AsWing组件又可以当作Sprite使用。

这个涂鸦板有一个“Undo”按钮,可以删除刚刚绘制的一笔。在鼠标离开框架的时候,整个框架会使用一个模糊滤镜。

Code:

 

package 
{
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.filters.BlurFilter;
	import flash.geom.Point;
	import org.aswing.ASColor;
	import org.aswing.AsWingManager;
	import org.aswing.BorderLayout;
	import org.aswing.Container;
	import org.aswing.FlowLayout;
	import org.aswing.JButton;
	import org.aswing.JFrame;
	import org.aswing.JPanel;
	import org.aswing.border.LineBorder;
	import org.aswing.graphics.Graphics2D;
	import org.aswing.graphics.IBrush;
	import org.aswing.graphics.Pen;
	import org.aswing.graphics.SolidBrush; 

	[SWF (width=600, height=500, frameRate=50)]
	public class DrawingBoard extends Sprite 
	{ 
		private var shapes:Array = new Array(); //在定义的时候对 Array 赋初值是一个好习惯
		private var pen:Pen = new Pen(ASColor.BLACK, 3);
		private var brush:IBrush = new SolidBrush(ASColor.BLACK);
		private var lastPoint:Point;
		private var drawing:Boolean = false;
		private var currentShape:Shape;
		private var frame:JFrame;
		private var canvas:JPanel;
		private var blur:BlurFilter = new BlurFilter();
		
		public function DrawingBoard() 
		{
			super();
			this.addEventListener(Event.ADDED_TO_STAGE, this.init);
		}
		private function init(e:Event) :void
		{
			AsWingManager.initAsStandard(this);
			this.frame = new JFrame(this, "Drawing board");
			this.frame.setSizeWH(540, 400);
			var c:Container = this.frame.getContentPane();
			this.canvas = new JPanel();
			this.canvas.setOpaque(true);
			this.canvas.setBackground(new ASColor(0xFFFFFF));
			this.canvas.setBorder(new LineBorder());
			c.append(this.canvas, BorderLayout.CENTER);

			var buttonPanel:JPanel = new JPanel(new FlowLayout());
			c.append(buttonPanel, BorderLayout.WEST);
			var undoBtn:JButton = new JButton("Undo");
			undoBtn.addEventListener(MouseEvent.CLICK, this.undo);
			buttonPanel.append(undoBtn);
			this.configure();
			this.frame.show();
		}
		private function configure() :void 
		{ 
			this.canvas.addEventListener(MouseEvent.MOUSE_DOWN, this.onMouseDown);
			this.canvas.addEventListener(MouseEvent.MOUSE_UP, this.onMouseUp);
			this.canvas.addEventListener(MouseEvent.MOUSE_MOVE, this.onMouseMove);
			this.frame.addEventListener(MouseEvent.ROLL_OUT, this.onRollOut);
			this.frame.addEventListener(MouseEvent.ROLL_OVER, this.onRollOver);
		}
		private function undo(e:MouseEvent) :void 
		{
			var shape:Shape = this.shapes.pop();
			if (shape != null)
			{
				this.canvas.removeChild(shape);
			}
		}

		private function onMouseDown(e:MouseEvent) :void 
		{
			this.currentShape = new Shape();
			this.canvas.addChild(this.currentShape);

			this.lastPoint = new Point(e.localX, e.localY);
			this.drawing = true;
		}
		private function onMouseUp(e:MouseEvent) :void 
		{
			if (this.currentShape != null) 
			{
				this.canvas.addChild(this.currentShape);
				this.shapes.push(this.currentShape);
			}
			this.drawing = false;
		}
		private function onMouseMove(e:MouseEvent) :void 
		{
			if (this.drawing)
			{
				var point:Point = new Point(e.localX, e.localY);
				var g:Graphics2D = new Graphics2D(this.currentShape.graphics);
				g.drawLine(this.pen, this.lastPoint.x, this.lastPoint.y, point.x, point.y);
				this.lastPoint = point;
			}
		}
		private function onRollOut(e:MouseEvent) :void 
		{
			this.drawing = false;
			this.frame.filters = [this.blur];
		}
		private function onRollOver(e:MouseEvent) :void 
		{ 
			this.frame.filters = [];
		}
	}
}


Notes!

在定义类的时候,我们用了一个[SWF (width=600, height=500, frameRate=50)]标记,这个标记告诉编译器目标SWF的大小是800像素宽,500像素高,帧速是50帧/秒。

ActionScript3.0支持标记,除了SWF标记之外,常用的标记还有 [Event] 和 [Embed],在本书的附录当中将会介绍这些常用的标记。

在构造函数当中,我们侦听了一个ADDED_TO_STAGE事件,这个事件会在一个DisplayObject被添加到舞台上的时候被触发。我们不再在构造函数当中直接做初始化,而是在ADDED_TO_STAGE事件的事件处理函数(init(Event):void {…})当中做初始化。因为在一个Sprite创建的时候它也许还没有被添加到舞台,这时候,Sprite的stage引用还没有被设置,这时候做初始化有可能会造成一些计算上的错误。所以我们将会在Sprite被添加到舞台上之后再来进行初始化。

---------------------------------------------------------------------------------------------------------------------

Attention!

在ADDED_TO_STAGE事件的处理函数当中进行初始化是一个良好的习惯,我们将建议你用这样的习惯。这会使你的程序有更好的兼容性。

---------------------------------------------------------------------------------------------------------------------

用一个JPanel作为画布。这是因为JPanel是Sprite的子类,我们可以像操作Sprite一样操作JPanel。JPanel默认是透明的,为了能够在上面绘画,我们把它设为不透明的,并且将背景颜色设为白色(0xFFFFFF)。如下:

this.canvas.setOpaque(true);
this.canvas.setBackground(new ASColor(0xFFFFFF));

---------------------------------------------------------------------------------------------------------------------

为了让画布的边缘更加明显,我们给画布加了边框(Border)。setBorder方法继承自Component,所有的AsWing控件都有这个方法。AsWing支持很多种边框,LineBorder是线状边框。常用作组件边界的标识。默认的LineBorder是直角,黑色,宽度为1像素的矩形线框。如下:

this.canvas.setBorder(new LineBorder());

---------------------------------------------------------------------------------------------------------------------

每一笔的绘制从鼠标按下开始,到鼠标离开画布或者鼠标弹起结束。在鼠标按下的时候,我们新建了一个Shape对象,将这个对象加入到画布的显示队列当中(addChild),如下:

this.currentShape = new Shape();
this.canvas.addChild(this.currentShape);


---------------------------------------------------------------------------------------------------------------------

为了记录绘图的过程,我们把每一笔作为一个Shape对象添加到画布(这时候,JPanel应当被看作是一个Sprite)的最上层。同时把这个Shape的引用加入到一个Array当中。在Undo的时候,我们从这个Array当中取出最新的一笔(Shape)的引用,通过这个引用从画布上删除这一笔。如下:

private function undo(e:MouseEvent) :void 
{
 var shape:Shape = this.shapes.pop();
 if (shape != null)
  {
  this.canvas.removeChild(shape);
 }
}


---------------------------------------------------------------------------------------------------------------------

Test:

1.给这个画图板添加更多功能,比如绘制矩形、绘制椭圆。

2.你可以把整个绘制过程记录下来,以SVG保存。关于SVG的详细信息,可以参看SVG中国的文档http://www.chinasvg.com/


---------------------------------------------------------------------------------------------------------------------

API:flash.events.Event


Event.ADDED_TO_STAGE:

在对象被加入到舞台(Stage)的显示队列当中的时候触发这个事件。一般来说,不要在构造函数当中直接初始化,而是在ADDED_TO_STAGE事件的处理函数当中初始化,这样可以避免一些初始化错误,程序的兼容性更强。


API:org.aswing.Component


setOpaque(b:Boolean):void

组件背景是否不透明,false为透明,true为不透明


setBackground(c:ASColor):void

设置组件的背景颜色,一般这个方法是和setOpaque配合使用的。只有背景是不透明的情况下才能看到背景颜色。


setBorder(b:Border):void

设置边框。


API:flash.events.MouseEvent


MouseEvent.CLICK

常数,鼠标点击事件,一次鼠标点击事件=鼠标按下+鼠标弹起。所以,鼠标按下事件和鼠标弹起事件会和鼠标点击事件一起被触发。


MouseEvent.MOUSE_DOWN

常数,鼠标按下事件,当鼠标在对象上方按下的时候触发。如果对象被


MouseEvent.MOUSE_UP

常数,鼠标弹起事件,当鼠标在对象上方弹起的时候触发


MouseEvent.MOUSE_MOVE

常数,鼠标移动事件,鼠标移动的时候触发。系统底层事件,两次事件之间的周期与帧速无关。


MouseEvent.ROLL_OUT

常数,鼠标滑出对象事件,鼠标滑出对象的时候触发。


MouseEvent.ROLL_OVER

常数,鼠标滑入对象事件,鼠标滑入对象进入对象上空区域的时候触发。


localX:Number

属性,鼠标当前的X坐标,参考系是当前对象的局部坐标系。


localX:Number

属性,鼠标当前的Y坐标,参考系是当前对象的局部坐标系。


API:flash.filters.BlurFilter


BlurFilter(blurX:Number=4.0, blurY:Number=4.0, auality:int=1.0)

构造函数,模糊滤镜。


API:flash.display.DisplayObject


filters:Array

属性,可读可写,滤镜列表,显示对象将依次使用队列当中的滤镜。


API:Array


pop() :Object

弹出队列尾端的元素(栈顶)。


push(o:Object) :void

把一个元素加到队列的尾端(栈顶)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值