本人一直都是在.NET平台上混饭吃的,没想到第一篇博文居然献给了Flex,呵呵!在做B/S的开发中,HTML+JavaScript+Ajax在单纯的数据处理和表现上能完成的很好,但在其他的一些方面,例如客户端画图,就显的有些力不从心了。由于项目需要,我开始转向于其他的RIA技术(Flex or SilverLight)。网上关于Flex and SilverLight的争论纷纷扰扰,我的看法是两个技术都应该学,其实这两个技术的学习成本是比较低的,SilverLight可以用C#,Flex使用的ActionScript基本上就是强数据类型的JavaScript,有网页开发经验的人都可以很容易上手。要是在Windows平台上部署的的话,我会首选SilverLight,毕竟都是MS自家的技术,要是Linux就选Flex咯,虽说有个跨平台版的SilverLight(Mono的MoonLight),但个人并不是很看好。
呵呵,闲扯了一段,现在切入主题。本文主要介绍使用ActionScript实现跟随鼠标移动画直线的一种方法,所谓跟随鼠标移动画直线意思是当点击鼠标的时候,确定画直线的起点,当鼠标移动的时候,从起点到鼠标当前的坐标画直线作为预览,当再次点击鼠标的时候从起点到鼠标点击的地方画出一条直线,类似于Windows画图板的画直线功能。我在这里采用GDI画图时常用到的双缓存思想,其实原理也很简单,设置两个画布_canvasTop和_canvasBottom,_canvasTop叠加在_canvasBottom上,将_canvasTop的背景设为透明,点击鼠标确定画线的开始点,当鼠标移动时,先擦除_canvasTop上原来的直线,然后以鼠标当前的坐标为画线结束点重新画线,其实就是总是保持_canvasTop上个有一根直线,当再次点击鼠标的时候,确定了画线的结束点,在_canvasBottom上画下直线,由于_canvasTop是透明的,_canvasBottom上的才是最终想要的画图结果,在_canvasTop上的擦除操作不会影响到_canvasBottom的显示结果。用这种方法实现的效果还是很好的,画线过程中很流畅,也不会出现屏幕闪烁的现象。
本人也是刚开始接触ActionScript,对于Flex的机制还不甚了解,不知道这种做法是否妥当,如果大家有更好的实现办法,欢迎拍砖:-)
源代码:
2 * Guojian.Lv
3 * 2008-12-04
4 * 跟随鼠标移动画直线
5 */
6 package {
7 //
8 import flash.display.Sprite;
9 import flash.events.ContextMenuEvent;
10 import flash.events.MouseEvent;
11 import flash.ui.ContextMenu;
12 //
13 [SWF(width="800",height="600",backgroundColor="0x000000")]
14 public class DrawLine extends Sprite{
15 //画线开始点
16 private var _xStart:int = 0;
17 private var _yStart:int = 0;
18 //标志位,为true时开始画线、false不动作
19 private var _bFlag:Boolean = false;
20 //画布
21 private var _canvasTop:Sprite; //顶层画布(作为临时画布,透明背景)
22 private var _canvasBottom:Sprite; //底层画布(实际保存图像的画布,黑色背景)
23 //
24 public function DrawLine(){
25 _canvasBottom = new Sprite();
26 addChild(_canvasBottom);
27 _canvasBottom.graphics.lineStyle(1, 0xFFFFFF, 1);
28 _canvasBottom.graphics.beginFill(0x000000);
29 _canvasBottom.graphics.drawRect(0, 0, 800, 600);
30 _canvasBottom.graphics.endFill();
31 //
32 _canvasTop = new Sprite();
33 _canvasBottom.addChild(_canvasTop);
34 _canvasTop.graphics.lineStyle(1, 0xFFFFFF, 1);
35 _canvasTop.graphics.beginFill(0xFFFFFF, 0);
36 _canvasTop.graphics.drawRect(0, 0, 800, 600);
37 _canvasTop.graphics.endFill();
38 //
39 _canvasTop.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
40 _canvasTop.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
41 //
42 _canvasTop.contextMenu = new ContextMenu();
43 _canvasTop.contextMenu.hideBuiltInItems();
44 _canvasTop.contextMenu.addEventListener(ContextMenuEvent.MENU_SELECT, onContextMenu);
45 }
46
47 //鼠标单击事件
48 private function onMouseDown(event:MouseEvent):void{
49 if (_bFlag){
50 //true时在底层画布画线
51 _canvasBottom.graphics.moveTo(_xStart, _yStart);
52 _canvasBottom.graphics.lineTo(mouseX, mouseY);
53 }
54 else{
55 _xStart = mouseX;
56 _yStart = mouseY;
57 }
58 _bFlag = !_bFlag;
59 }
60
61 //鼠标移动事件
62 private function onMouseMove(event:MouseEvent):void{
63 if (_bFlag){
64 //当鼠标移动,擦除上次画的线,重新画线
65 _canvasTop.graphics.clear();
66 //
67 _canvasTop.graphics.beginFill(0xFFFFFF, 0);
68 _canvasTop.graphics.drawRect(0, 0, 800, 600);
69 _canvasTop.graphics.endFill();
70 //
71 _canvasTop.graphics.lineStyle(1, 0xFFFFFF, 1);
72 _canvasTop.graphics.moveTo(_xStart, _yStart);
73 _canvasTop.graphics.lineTo(mouseX, mouseY);
74 }
75 }
76
77 //右键终止画图动作
78 private function onContextMenu(event:ContextMenuEvent):void{
79 _bFlag = false;
80 _canvasTop.graphics.clear();
81 _canvasTop.graphics.beginFill(0xFFFFFF, 0);
82 _canvasTop.graphics.drawRect(0, 0, 800, 600);
83 _canvasTop.graphics.endFill();
84 }
85 }
86}