爱程序网

Flash在线签名小程序,可回放,动态导出gif图片

来源: 阅读:

需求:

公司为了使得和客户领导签字的时候记录下来,签字过程,可以以后动态回放演示,最好是gif图片,在网页上也容易展示,文件也小。

解决过程

    始我们去寻找各种app,最终也没有找到合适的,后来我在flash8上看到有个在线的手绘板,很适合我们的需求,但是我尝试了很多次

绘画完成后,导出的是swf文件,我想从这个swf文件中抽出图片,最终发现这个导出的swf里面根本不存在我绘画的记录过程。

网上确实有手绘板的代码,但是没有动态回放的功能及到处gif图片的功能,还是不满足我们需求,

     索性自己写了一个flash小程序实现手绘画板及动态回放功能。我把具体的思路及详细代码都贴出来,

希望能给有用到的人带来方便。

整体思路:

  1. 编写一个flash程序,实现基本手绘板功能
  2. 在基础上实现回放功能(这里是难点)
  3. 创建一个asp.ne站点,写个一般处理程序GetSignImg.ashx,用于存储flash发布时候动态创建的jpg图片
  4. 当swf程序发布后点击下载的时候,后台程序将所有的jpg图片拼成gif图片导出(使用了Gif.Components.dll)。

截图:

 

具体过程

 一、实现手绘板功能,在网上能找到很多代码,这块也简单。

 二、在基础上实现回放功能,我重点讲下这里的实现,起初我是这么判断的,当鼠标MOUSE_DOWN时候开始记录画笔当前位置信息存入一个数组中(包含X,Y坐标值),

     鼠标MOUSE_UP的时候,这个数组存储结束,开启一个新的数组用于点的信息。当回放的时候,将这些所有数组中的点的信息重新绘制一遍,包括flash8.net的实现都是这么干的

     如果一笔绘制很长,当它回放的时候一下子全显示出来,没有一个绘制的过程。后来领导说这样不行,因为领导签字的时候很多都是一笔走完,最后我想了一个解决的办法,

     就是在回放的时候设置一个阀值,比如50个点,够50个点就回放一次,这样一来,即使领导签字是一笔,回放的时候效果也会很好。

    下面是所有ActinScipt源码

   

  1 import flash.ui.Mouse;
  2 import flash.display.BitmapData;
  3 import com.adobe.images.JPGEncoder;
  4 import flash.events.MouseEvent;
  5 
  6 var linesize:uint = 2;//画笔大小
  7 var isDown:Boolean = false;
  8 var oldX:Number;
  9 var oldY:Number;
 10 var arrayBig:Array=new Array();//存放笔画的数组,外层数组
 11 var num:uint = 0;//当前数组个数
 12 var playNum:uint = 0;//当前回放的数字(代表当前回放到第几个数组了)
 13 var intervalDuration:Number = 500;// 回放延时时间间隔
 14 var relaseDuration:Number = 1000;//发布时时间间隔
 15 var intervalId:uint;//回放循环的ID 
 16 var relaseId:uint;//发布的ID
 17 var url = "http://www.wispdawn.com/";//暂用我的网站做服务器
 18 var serviceFile = "GetSignImg.ashx";//服务文件
 19 
 20 mc_canvas.addEventListener(MouseEvent.MOUSE_DOWN ,onDown);
 21 mc_canvas.addEventListener(MouseEvent.MOUSE_UP ,onUp);
 22 mc_canvas.addEventListener(MouseEvent.MOUSE_MOVE ,onMove);
 23 mc_canvas.addEventListener(MouseEvent.MOUSE_OVER,onMouseOver);
 24 mc_canvas.addEventListener(MouseEvent.MOUSE_OUT,onMouseOut);
 25 
 26 
 27 
 28 function onDown(event:MouseEvent):void
 29 {
 30     arrayBig[num]=new Array();//这里设置为数组
 31     isDown = true;
 32     oldX = mouseX;
 33     oldY = mouseY;
 34 }
 35 function onMove(event:MouseEvent):void
 36 {
 37     if (isDown)
 38     {
 39         mc_canvas.graphics.lineStyle(linesize);
 40         mc_canvas.graphics.moveTo(oldX,oldY);
 41         mc_canvas.graphics.lineTo(mouseX,mouseY);
 42         oldX = mouseX;
 43         oldY = mouseY;
 44         arrayBig[num].push([oldX,oldY]);
 45         if (arrayBig[num].length > 80)
 46         {
 47             //isDown = false;
 48             trace(num);
 49             num++;//数组个数+1
 50             arrayBig[num]=new Array();
 51             arrayBig[num].push([oldX,oldY]);
 52         }
 53     }
 54 }
 55 
 56 function onUp(event:MouseEvent):void
 57 {
 58     isDown = false;
 59     trace(num);
 60     num++;//数组个数+1
 61 }
 62 
 63 function onMouseOver(event:MouseEvent):void
 64 {
 65     mc_canvas.addEventListener(Event.ENTER_FRAME, onEnter);
 66 }
 67 
 68 
 69 function onMouseOut(event:MouseEvent):void
 70 {
 71     mc_canvas.removeEventListener(Event.ENTER_FRAME, onEnter);
 72     Mouse.show();
 73     mc_pen.visible = false;
 74 }
 75 
 76 //画布监听事件
 77 function onEnter(event:Event):void
 78 {
 79     Mouse.hide();
 80     mc_pen.visible = true;
 81     mc_pen.x = mouseX + 22;
 82     mc_pen.y = mouseY + 22;
 83 }
 84 
 85 
 86 
 87 //清空
 88 btn_clear.addEventListener(MouseEvent.CLICK,onClear);
 89 function onClear(event:MouseEvent):void
 90 {
 91     arrayBig = [];
 92     playNum = 0;
 93     num = 0;
 94     mc_canvas.graphics.clear();
 95 }
 96 //保存;
 97 btn_save.addEventListener(MouseEvent.CLICK,onSave);
 98 function onSave(event:MouseEvent):void
 99 {
100     var imager:BitmapData = new BitmapData(mc_canvas.width,mc_canvas.height);
101     imager.draw(mc_canvas);
102     var jpg:JPGEncoder = new JPGEncoder(100);
103     var file:FileReference = new FileReference();
104     file.save(jpg.encode(imager),"sign.jpg");
105 
106 }
107 
108 //回放按钮
109 btn_replay.addEventListener(MouseEvent.CLICK,onReplay);
110 function onReplay(event:MouseEvent):void
111 {
112     if (arrayBig.length > 0)
113     {
114         mc_canvas.graphics.clear();
115         //清除画面;
116         playNum = 0;//初始为0
117         intervalId = setInterval(onReplayDelay,intervalDuration);
118     }
119 }
120 
121 //用于设置循环的回放
122 function onReplayDelay():void
123 {
124     //当前笔画
125     var arr:Array = arrayBig[playNum];
126     //当前笔画下面所有的点
127     for (var i:uint=0; i<arr.length-1; i++)
128     {
129         var curPoint = arr[i];
130         var nexPoint = arr[i + 1];
131         mc_canvas.graphics.lineStyle(linesize);
132         mc_canvas.graphics.moveTo(curPoint[0],curPoint[1]);
133         mc_canvas.graphics.lineTo(nexPoint[0],nexPoint[1]);
134     }
135 
136     playNum++;
137     if (playNum==num)
138     {
139         clearInterval(intervalId);
140     }
141 }
142 
143 //上传图片
144 function UpImg(seq:uint):void
145 {
146     var imager:BitmapData = new BitmapData(mc_canvas.width,mc_canvas.height);
147     imager.draw(mc_canvas);
148     var jpg:JPGEncoder = new JPGEncoder(100);
149     var bytes:ByteArray = jpg.encode(imager);
150 
151     var signName:String = mc_mask.txt_name.text;
152     var req:URLRequest = new URLRequest(url+serviceFile+"?name="+signName+"&seq="+seq+"&total="+arrayBig.length);
153     req.data = bytes;
154     req.method = URLRequestMethod.POST;
155     req.contentType = "application/octet-stream";
156 
157     var loader:URLLoader = new URLLoader();
158     loader.dataFormat = URLLoaderDataFormat.BINARY;
159     loader.load(req);
160 }
161 //loader.addEventListener(Event.COMPLETE, completeHandler);
162 
163 //function completeHandler(evt:Event):void
164 //{
165 //trace(evt.target.data);
166 //}
167 
168 //发布
169 btn_release.addEventListener(MouseEvent.CLICK,onReleas);
170 function onReleas(event:MouseEvent):void
171 {
172     if (arrayBig.length > 0)
173     {
174         mc_mask.x = mc_mask.y = 0;
175         mc_mask.mc_mask_bg.alpha = 0.8;
176         mc_mask.btn_complete.visible = false;//隐藏完成
177         mc_mask.btn_down.visible = false;//隐藏下载
178     }
179 }
180 //真正发布事件执行
181 function Release():void
182 {
183     //当前笔画
184     var arr:Array = arrayBig[playNum];
185     //当前笔画下面所有的点
186     for (var i:uint=0; i<arr.length-1; i++)
187     {
188         var curPoint = arr[i];
189         var nexPoint = arr[i + 1];
190         mc_canvas.graphics.lineStyle(linesize);
191         mc_canvas.graphics.moveTo(curPoint[0],curPoint[1]);
192         mc_canvas.graphics.lineTo(nexPoint[0],nexPoint[1]);
193     }
194     //上传图片;;
195     UpImg(playNum);
196     playNum++;
197     if (playNum==num)
198     {
199         clearInterval(relaseId);
200         AfterRelease();
201     }
202 }
203 //取消发布
204 mc_mask.btn_cancel.addEventListener(MouseEvent.CLICK,onCancel);
205 function onCancel(event:MouseEvent):void
206 {
207     mc_mask.x = 10000;
208     mc_mask.mc_mask_bg.alpha = 0;
209 }
210 //真正发布按钮
211 mc_mask.btn_release.addEventListener(MouseEvent.CLICK,onTrueRelease);
212 function onTrueRelease(event:MouseEvent):void
213 {
214     var name1 = mc_mask.txt_name.text;
215     if (name1!="")
216     {
217         BeginRelease();
218         mc_canvas.graphics.clear();
219         playNum = 0;
220         relaseId = setInterval(Release,relaseDuration);
221     }
222     else
223     {
224         mc_mask.txt_state.text = "请输入姓名";
225     }
226 }
227 //发布前设置
228 function BeginRelease():void
229 {
230     mc_mask.btn_release.visible = false;
231     mc_mask.btn_cancel.visible = false;
232     mc_mask.txt_name.visible = false;
233     mc_mask.txt_nameTile.visible = false;
234     mc_mask.txt_state.text = "正在发布...";
235 }
236 //发布后设置
237 function AfterRelease():void
238 {
239     mc_mask.btn_complete.visible = true;
240     mc_mask.btn_down.visible = true;
241     mc_mask.btn_complete.addEventListener(MouseEvent.CLICK,onComplete);
242     mc_mask.txt_state.text = "发布完成";
243 
244 }
245 //发布完成
246 function onComplete(event:MouseEvent):void
247 {
248     mc_mask.x = 10000;
249     mc_mask.mc_mask_bg.alpha = 0;
250     mc_mask.btn_down.visible = true;
251     mc_mask.btn_release.visible = true;
252     mc_mask.btn_cancel.visible = true;
253     mc_mask.txt_name.visible = true;
254     mc_mask.txt_nameTile.visible = true;
255     mc_mask.txt_state.text = "";
256     mc_mask.txt_name.text = "";
257 }
258 
259 //下载gif
260 mc_mask.btn_down.addEventListener(MouseEvent.CLICK,onDownGif);
261 function onDownGif(event:MouseEvent):void
262 {
263     var today:Date =new Date();
264     var todayStr = getDateFormat(today);//获取当天日期例如 20131130
265     var signName:String = mc_mask.txt_name.text;
266 
267     var gifUrl:URLRequest = new URLRequest(url+"/Img/"+signName+"_"+todayStr+"/"+signName+".gif");
268     var fileRef:FileReference=new FileReference();
269     //fileRef.addEventListener(ProgressEvent.PROGRESS,onProgress);
270     fileRef.download(gifUrl,"sign.gif");
271 }
272 function onProgress(event:ProgressEvent):void
273 {
274     var loaded:uint = event.bytesLoaded;
275     var total:uint = event.bytesTotal;
276 }
277 
278 //获取当天日期
279 function getDateFormat( date:Date):String
280 {
281     var dYear:String = String(date.getFullYear());
282     var dMonth:String = String((date.getMonth() + 1 < 10) ? "0" : "") + (date.getMonth() + 1);
283     var dDate:String = String(date.getDate() < 10 ? "0":"") + date.getDate();
284     return dYear+dMonth+dDate;
285 }
View Code

 

 三、创建一个asp.ne站点,写个一般处理程序GetSignImg.ashx

       这里就是用于的获取flash传递过来的图片,获取后导出jpg图片序列,然后将这些序列图片用程序生成一个gif图片存放在目录下,当flash点击到处gif图片时候,执行下载

       源文件如下

      

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.IO;
 6 using System.Drawing.Drawing2D;
 7 using System.Drawing.Imaging;
 8 using Gif.Components;
 9 
10 namespace Web
11 {
12     /// <summary>
13     /// GetSignImg1 的摘要说明
14     /// </summary>
15     public class GetSignImg1 : IHttpHandler
16     {
17         public void ProcessRequest(HttpContext context)
18         {
19             string name = context.Request["name"];
20             int seq = Convert.ToInt32(context.Request["seq"]);
21             int total =Convert.ToInt32(context.Request["total"]);
22             int length = context.Request.TotalBytes;
23             byte[] buffer = context.Request.BinaryRead(length);
24             string newPath=HttpContext.Current.Server.MapPath("Img/" + name + "_"+DateTime.Now.ToString("yyyyMMdd"));
25             if (!Directory.Exists(newPath))
26             {
27                 Directory.CreateDirectory(newPath);
28             };
29             string path = string.Format("{0}/{1}.jpg", newPath, seq);
30             FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write);
31             BinaryWriter bw = new BinaryWriter(fs);
32             bw.Write(buffer);
33             bw.Close();
34             fs.Close();
35 
36             //下载gif
37             if (seq + 1 == total)
38             {
39                 //生成gif图片               
40                 List<string> fileList = new List<string>();
41                 for (int i = 0; i < total; i++)
42                 {
43                     fileList.Add(newPath + "/" + i + ".jpg");
44                 }
45                 string[] imageFilePaths = fileList.ToArray();
46                 string outputFilePath = newPath + "/" + name + ".gif";
47                 AnimatedGifEncoder e = new AnimatedGifEncoder();
48                 e.Start(outputFilePath);
49                 //图片转换时间
50                 e.SetDelay(50);
51                 //1表示只动一次,0:表示循环,n:表示循环n次
52                 e.SetRepeat(1);
53                 for (int i = 0, count = imageFilePaths.Length; i < count; i++)
54                 {
55                     e.AddFrame(System.Drawing.Image.FromFile(imageFilePaths[i]));
56                 }
57                 e.Finish();
58             }
59         }
60 
61         public bool IsReusable
62         {
63             get
64             {
65                 return false;
66             }
67         }
68     }
69 }
GetSignImg.ashx.cs

 

 四、所有程序打包下载 Download

关于爱程序网 - 联系我们 - 广告服务 - 友情链接 - 网站地图 - 版权声明 - 人才招聘 - 帮助