2007/02/13 | 鼠标控制画曲线及扇形问题的分析(一)
类别(Flash课件设计) | 评论(4) | 阅读(711) | 发表于 16:27

鼠标控制画曲线及扇形问题的分析(一)

独自行走

 

知识点:鼠标关联动作的识别与分析,程序逻辑的逐步实现,画线及填充命令的应用。

画直线、方框、整圆的方法,在我的《Flash 画线功能的讨论》一文中已经解决了,现在有一个新问题,怎样来画曲线和扇形呢?

这两个问题与前面的问题看起来很近似,但程序逻辑上要更复杂一些。在画直线的过程中,我们只要不停的清除、再重新画线,鼠标抬起时,就结束画线,就可以了。也就是说在鼠标按下、拖动、抬起这一次过程中,就可以完成任务。但是在画曲线时,我们在第一轮的鼠标按下、拖动、抬起时,只能先确定一个起始点、终结点,第二轮的鼠标操作时,才能完成把直线拉开成曲线的步骤。而后,在下次鼠标操作之前,鼠标应该是不对屏幕进行操作的。

从前面的对比中我们可以看到,鼠标需要进行两轮操作才能实现画一次曲线,加上鼠标画完线后,在屏幕上空跑的状态,可以将这些情形汇总成三个状态,如果用一个数值变量来表示它可以是myStep = 0,1,2,如果用两个逻辑变量来表示(可以组合成四种状态),它可以是 isA&&isB, !isA&&isB, !isA&&!isB,在这里我采用数值变量来表示三种状态。

很容易想到的一个结构就是switch(){}结构,我们可以在鼠标的各个事件中都加入这一结构,优化代码的问题我们暂时先不考虑。

示意代码如下(依旧是用侦听器模式来画线):

var myStep:Number = 2;

var myListener:Object = new Object();

myListener.onMouseDown = function() {

       switch (myStep) {

       case 0 :

              //记录起点位置

              break;

       case 1 :

              //记录控制点位置

              break;

       case 2 :

              //记录起点位置

                     myStep = 0;

              break;

       default :

       }

};

myListener.onMouseMove = function() {

       switch (myStep) {

       case 0 :

              //从起点画直线到鼠标当前位置

              break;

       case 1 :

              //从起点画曲线到结束点,鼠标当前位置为控制点的位置

              break;

       case 2 :

              //什么都不做

       default :

       }

};

myListener.onMouseUp = function() {

       switch (myStep) {

       case 0 :

              //记录结束点位置

              myStep++;

              break;

       case 1 :

              //结束画曲线

              myStep++;

              break;

       case 2 :

              //什么都不做

       default :

       }

};

Mouse.addListener(myListener);

如果myStep初始值为0,那么一开始,鼠标运动时,系统会自动的画起线来,所以,我们让myStep的初始值为2,按下后变成0,这样做之后,鼠标按下时永远都不会进入myStep0的状态,这对我们的程序没有影响,属于代码优化的问题,所以也暂时不去考虑,总之每个事件中都加入switch结构,便于我们对不同状态的理解。

现在加入画直线的代码,完成后效果如下:

this.createEmptyMovieClip("circle_mc", this.getNextHighestDepth());

circle_mc._x = 200;

circle_mc._y = 208;

var cur_mc = circle_mc;

//

var start_pt:Object = new Object();

var end_pt:Object = new Object();

//

var myStep:Number = 2;

var myListener:Object = new Object();

myListener.onMouseDown = function() {

       switch (myStep) {

       case 0 :

              //记录起点位置

              start_pt._x = cur_mc._xmouse;

              start_pt._y = cur_mc._ymouse;

              break;

       case 1 :

              //记录控制点位置

              break;

       case 2 :

              //记录起点位置

              start_pt._x = cur_mc._xmouse;

              start_pt._y = cur_mc._ymouse;

              myStep = 0;

              break;

       default :

       }

};

myListener.onMouseMove = function() {

       switch (myStep) {

       case 0 :

              //从起点画直线到鼠标当前位置

              cur_mc.clear();

              cur_mc.lineStyle(1, 0x00ff00, 80);

              cur_mc.moveTo(start_pt._x, start_pt._y);

              cur_mc.lineTo(cur_mc._xmouse, cur_mc._ymouse);

              break;

       case 1 :

              //从起点画曲线到结束点,鼠标当前位置为控制点的位置

              break;

       default :

       }

};

myListener.onMouseUp = function() {

       switch (myStep) {

       case 0 :

              //记录结束点位置

              end_pt._x = cur_mc._xmouse;

              end_pt._y = cur_mc._ymouse;

              myStep++;

              break;

       case 1 :

              //结束画曲线

              myStep++;

              break;

       default :

       }

};

Mouse.addListener(myListener);

可以看到现在实现的效果是按下画线,抬起、再按下时,什么也没做,第三轮按下时,画一个直线,这让你很容易想到第二轮的画线时该画曲线了。OK加入曲线的代码。

直接加入画曲线的代码:

cur_mc.clear();

cur_mc.lineStyle(1, 0x00ff00, 80);

cur_mc.moveTo(start_pt._x, start_pt._y);

cur_mc.curveTo(cur_mc._xmouse, cur_mc._ymouse, end_pt._x, end_pt._y);

可以发现,第一轮画完直线后,鼠标再移动时,直接就变成曲线了,还没等到第二轮的开始,这问题怎么解决呢?再加个变量canDrawCur,初始值为false,表示不允许画曲线,第二轮按下鼠标时,才允许画线令canDrawCur= true,第二轮抬起时,停止画曲线 canDrawCur = false。这样以来,画曲线的动作就完成了。

为了让曲线的效果更好看,还可以在移动曲线的时候,画两个辅助线,抬起时清屏再画一次,起到隐藏辅助线的效果。完成的代码如下:

this.createEmptyMovieClip("circle_mc", this.getNextHighestDepth());

circle_mc._x = 0;

circle_mc._y = 0;

var cur_mc = circle_mc;

var canDrawCur = false;

//

var start_pt:Object = new Object();

var end_pt:Object = new Object();

//

var myStep:Number = 2;

var myListener:Object = new Object();

myListener.onMouseDown = function() {

       switch (myStep) {

       case 0 :

              //记录起点位置

              //start_pt._x = cur_mc._xmouse;

              //start_pt._y = cur_mc._ymouse;

              break;

       case 1 :

              //记录控制点位置

              canDrawCur = true;

              break;

       case 2 :

              //记录起点位置

              start_pt._x = cur_mc._xmouse;

              start_pt._y = cur_mc._ymouse;

              myStep = 0;

              break;

       default :

       }

};

myListener.onMouseMove = function() {

       switch (myStep) {

       case 0 :

              //从起点画直线到鼠标当前位置

              cur_mc.clear();

              cur_mc.lineStyle(1, 0x00ff00, 80);

              cur_mc.moveTo(start_pt._x, start_pt._y);

              cur_mc.lineTo(cur_mc._xmouse, cur_mc._ymouse);

              break;

       case 1 :

              //从起点画曲线到结束点,鼠标当前位置为控制点的位置

              if (canDrawCur) {

                     cur_mc.clear();

                     cur_mc.lineStyle(1, 0x00ff00, 80);

                     cur_mc.moveTo(start_pt._x, start_pt._y);

                     cur_mc.curveTo(cur_mc._xmouse, cur_mc._ymouse, end_pt._x, end_pt._y);

                     //添加辅助线

                     cur_mc.lineStyle(1, 0x000000, 50);

                     cur_mc.lineTo(cur_mc._xmouse, cur_mc._ymouse);

                     cur_mc.lineTo(start_pt._x, start_pt._y);

              }

              break;

       default :

       }

};

myListener.onMouseUp = function() {

       switch (myStep) {

       case 0 :

              //记录结束点位置

              end_pt._x = cur_mc._xmouse;

              end_pt._y = cur_mc._ymouse;

              myStep++;

              break;

       case 1 :

              //结束画曲线

              //重新画曲线,起到消除辅助线的目的。

              cur_mc.clear();

              cur_mc.lineStyle(1, 0x00ff00, 80);

              cur_mc.moveTo(start_pt._x, start_pt._y);

              cur_mc.curveTo(cur_mc._xmouse, cur_mc._ymouse, end_pt._x, end_pt._y);

              canDrawCur = false;

              myStep++;

              break;

       default :

       }

};

Mouse.addListener(myListener);

这里涉及的代码结构或许显得有些啰嗦,而且从完成后来看流程有些模糊,但这是实际测试后的结果,在我们开始设计时,只能够大致设计一个框架,最后再根据实际的效果在细节上下点功夫,最终的代码还有简化的余地,但这不是我在这里想讨论的,留给大家来处理。

尽管我尽量想用switch结构来避免使用逻辑变量,但在前面的代码里还是用到了一个逻辑变量canDrawCur,分析原因,这个逻辑变量是可以省略的,因为我将鼠标空跑当成一个状态来理解,实际上却有两种状态,其一是画完直线后,鼠标在下次按下之前需要空跑一下,其二,画完曲线后,鼠标需要空跑一下,也就是说总共有四种状态,再将代码改一下,结果如下:

this.createEmptyMovieClip("circle_mc", this.getNextHighestDepth());

circle_mc._x = 0;

circle_mc._y = 0;

var cur_mc = circle_mc;

//

var start_pt:Object = new Object();

var end_pt:Object = new Object();

//

var myStep:Number = 3;

var myListener:Object = new Object();

myListener.onMouseDown = function() {

       switch (myStep) {

       case 0 :

              break;

       case 1 :

              //第二次点击发生时,这里只起到一个中转的作用。

              myStep++;

              break;

       case 2 :

              break;

       case 3 :

              //首次点击发生时,记录起点位置

              start_pt._x = cur_mc._xmouse;

              start_pt._y = cur_mc._ymouse;

              myStep = 0;

              break;

       default :

       }

};

myListener.onMouseMove = function() {

       switch (myStep) {

       case 0 :

              //从起点画直线到鼠标当前位置

              cur_mc.clear();

              cur_mc.lineStyle(1, 0x00ff00, 80);

              cur_mc.moveTo(start_pt._x, start_pt._y);

              cur_mc.lineTo(cur_mc._xmouse, cur_mc._ymouse);

              break;

       case 1 :

              break;

       case 2 :

              //从起点画曲线到结束点,鼠标当前位置为控制点的位置

              cur_mc.clear();

              cur_mc.lineStyle(1, 0x00ff00, 80);

              cur_mc.moveTo(start_pt._x, start_pt._y);

              cur_mc.curveTo(cur_mc._xmouse, cur_mc._ymouse, end_pt._x, end_pt._y);

              //添加辅助线

              cur_mc.lineStyle(1, 0x000000, 50);

              cur_mc.lineTo(cur_mc._xmouse, cur_mc._ymouse);

              cur_mc.lineTo(start_pt._x, start_pt._y);

              break;

       default :

       }

};

myListener.onMouseUp = function() {

       switch (myStep) {

       case 0 :

              //第一轮画线结束,记录结束点位置

              end_pt._x = cur_mc._xmouse;

              end_pt._y = cur_mc._ymouse;

              myStep++;

              break;

       case 1 :

              break;

       case 2 :

              //第二轮画线结束,结束画曲线

              //重新画曲线,起到消除辅助线的目的。

              cur_mc.clear();

              cur_mc.lineStyle(1, 0x00ff00, 80);

              cur_mc.moveTo(start_pt._x, start_pt._y);

              cur_mc.curveTo(cur_mc._xmouse, cur_mc._ymouse, end_pt._x, end_pt._y);

              canDrawCur = false;

              myStep++;

              break;

       default :

       }

};

Mouse.addListener(myListener);

鼠标按下时共有四种状态可供选择,虽然对于我们这个例子,很多状态是用不着的,但这个结构却可以很容易的将连续的几步操作分隔开来,使我们能够很清楚的看到每一步该做什么,如用两个逻辑变量来控制实现画曲线的效果,那么代码的优化比较容易进行,因为两个逻辑变量之间有相关性,对它们的相关性的分析就可以将代码进一步简化,但从读代码的角度来看,却会增加一些额外的困难。

Google
0

评论Comments