20132-20更新:增加了加載圖片的縮放功能。將縮放后的寬度傳到動態頁,動態頁獲取后重新計算坐標位置后繪圖。如果涂鴉不和圖片合成,當寬度小于默認的650,繪制一條分隔線。
Asp.Net+flash+jquery實現的在線涂鴉插件,通過將涂鴉數據發送到ashx頁面,ashx獲取到數據后繪制圖片并保存涂鴉圖片。
本示例基于謾軻(Manction),http://manction.51.com簡易涂鴉板修改,增加了重做,畫筆顏色,大小和透明度,保存功能。
flash可以加載指定的站內圖片進行涂鴉,保存后繪制的數據和原始圖片合并生成新涂鴉圖片
示例
效果如下
test.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><script type="text/javascript" src="http://cdn.bootcss.com/jquery/1.7.1/jquery.min.js"></script><title>Asp.Net+flash+jquery.TY.js涂鴉插件,可保存涂鴉圖片</title><meta content="在線涂鴉,保存涂鴉圖片,asp.net保存涂鴉,flash涂鴉" name="Keywords"/><meta content="Asp.Net+flash+jquery實現的在線涂鴉插件,通過將涂鴉數據發送到ashx頁面,通過asp.net繪制圖片。" name="description"/><script type="text/javascript">window.onload=function(){ (function ($) { //cfg配置說明,JSON對象 //swf:涂鴉swf文件路徑,默認值為:ty.swf //height:高度,默認值為400,高度小于400會隱藏flash起來,最終生成的涂鴉圖片高度基于這個值。如果指定img將會忽略此配置,依據原始圖片尺寸 //width:寬度,默認值:650。注意:這里的寬度是最終生成的圖片寬度,不會改變UI的寬度,因為小于650會導致菜單顯示不全。最終生成的涂鴉圖片高度基于這個值。如果指定img將會忽略此配置,依據原始圖片尺寸 //img:flash要加載的圖片,繪制的涂鴉信息和此圖片合成,默認不加載圖片。只能加載站內圖片,站外圖片動態頁沒有添加圖片下載功能 //url:繪圖的涂鴉數據提交到的頁面,如果要保存圖片一定要傳遞此配置,否則無法保存圖片,不保存圖片時url,success和error回調可以不傳遞 //success:保存涂鴉時成功的回調函數,回調中的this為容器div對象,參數為返回的json對象 //error:保存涂鴉失敗時回調函數,回調中this為容器div對象,參數為返回的json對象 //data:ajax提交時附加的參數,JSON對象,如數據庫中對應ID什么的 //debug:如果為true,則輸出xhr返回的responseText信息 //ext:保存圖片擴展名,默認為jpg,不帶. //wstep:如果傳遞了img,每次縮放圖片寬度的大小,默認20。高度依據圖片原始尺寸等比算出 $.fn.TY = function (cfg) { var cbPrefix = 'doPost', cbMark = 'mark', tm, ie = !!document.all; function FlashVars(config) { var s = ''; if (config.cbName) s += '&cb=' + config.cbName; if (config.markName) s += '&mk=' + config.markName; if (config.img) s += '&img=' + config.img; else if (config.width < 650) s += '&spl=' + config.width; //寬度小于UI寬度則傳遞此參數給flash繪制分隔線 if (config.wstep) s += '&wstep=' + config.wstep; return s == '' ? '' : s.substring(1); } return this.each(function () { var me = $(this), config = $.extend({ swf: 'ty.swf', height: 400, width: 650, ext: 'jpg', wstep: 20 }, cfg); tm = new Date().getTime(); if (config.url) { //需要保存涂鴉圖片則注冊flash調用的javascript方法 config.cbName = cbPrefix + tm; //drawdata,字符串,結構:[{data:[[x,y],[x,y]...],lw:線條寬,color:線條顏色,alpha:線條透明度}.....] //newwidth:縮放后圖片寬度,發送到服務器用于計算縮放比率,矯正坐標用的,不是圖片忽略次參數 window[config.cbName] = function (drawdata, newwidth) { if (!drawdata) alert('沒有繪制涂鴉信息!'); else { window[config.markName]('正在保存圖片...'); var data = cfg.data ? cfg.data : {}; data.w = config.width; data.h = config.height; data.ext = config.ext; data.newwidth = newwidth; if (config.img) data.img = config.img; //這個也可以不傳,可以通過讀取數據庫獲取到原始圖片地址什么的,但是data對象要配置有記錄的ID data.drawdata = drawdata; $.ajax({ url: config.url, type: 'POST', data: data, complete: function (xhr) { window[config.markName]('none'); var r; if (200 == xhr.status) try { r = eval('(' + xhr.responseText + ')'); } catch (ex) { r = { success: false, err: '返回的JSON格式不正確!' + (config.debug ? '/n/n' + xhr.responseText : '') }; } else r = { success: false, err: 404 == xhr.status ? '動態頁路徑不對!' : '動態頁發生錯誤!' + (config.debug ? '/n/n' + xhr.responseText : '') }; if (r.success) { if (config.success) config.success.call(me.get(0), r); } else if (config.error) config.error.call(me.get(0), r); } }); } } } if (config.img || cfg.url) { config.markName = cbMark + tm; window[config.markName] = function (display) { if (display == 'none') me.find('div').hide(); else { me.find('div:last').html(display); me.find('div').show(); } } } me.css({ width: 650, height: config.height, overflow: 'hidden', position: 'relative', border: 'solid 1px #000000' }).append( ie ? '<object id="swf' + tm + '" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="650px" height="400px">' + '<param name="src" value="' + config.swf + '"><param name="FlashVars" value="' + FlashVars(config) + '"><param name="wmode" value="transparent"></object>' : '<embed width="650px" height="400px" id="swf' + tm + '" type="application/x-shockwave-flash" src="' + config.swf + '?' + FlashVars(config) + '" wmode="transparent"/>'); if (config.img || cfg.url) { me.append('<div style="background:#000000;' + (config.img ? '' : 'display:none;') + 'filter:alpha(opacity:50);opacity:.5;width:100%;height:100%;position:absolute;left:0px;height:100%;top:0px;"></div>'); me.append('<div style="position:absolute;left:43%;top:45%;color:#ffffff;' + (config.img ? '' : 'display:none;') + '">正在加載加載...</div>'); } }); }; })(jQuery); $('#dvTY').TY({ height: 300, width:200, img: '/imgdesign/ty/123.jpg', url: '/imgdesign/ty/save.ashx', swf: '/imgdesign/ty/ty.swf', data: { id: 123 }, //附加數據 debug: true, success: function (d) { alert('涂鴉保存成功!'); $('#dvRst').html('<a href="/imgdesign/ty/' + d.fn + '" target="_blank">點擊查看圖片</a>'); }, error: function (d) { alert(d.err); } }); }</script></head><body><div id="dvTY"></div><div id="dvRst"></div></body></html>
save.ashx
<%@ WebHandler Language="C#" Class="save" %>using System;using System.Web;using System.Drawing;using Newtonsoft.Json;using System.Collections.Generic;using System.IO;using System.Text.RegularExpressions;public class save : IHttpHandler { //drawdata結構:[{data:[[x,y],[x,y]...],lw:線條寬,color:線條顏色,alpha:線條透明度}.....] //每條線的信息 public class DrawData { private List<float[]> _data; private int _lw; private int _alpha; private string _color; /// <summary> /// 線條信息 /// </summary> public List<float[]> data { get { return _data; } set { _data = value; } } /// <summary> /// 畫筆寬 /// </summary> public int lw { get { return _lw; } set { _lw = value; } } /// <summary> /// 畫筆透明度,C#下是0~255,需要轉換一下 /// </summary> public int alpha { get { return (int)Math.Floor(_alpha * 2.55); } set { _alpha = value; } } /// <summary> /// 畫筆顏色 /// </summary> public string color { get { return _color; } set { _color = value; } } } /// <summary> /// 線條數組轉換為頂點數組 /// </summary> /// <param name="data">線條數據</param> /// <param name="IsImg">繪制在圖片上,不在25~h+25范圍內的數據去掉</param> /// <param name="h">圖片高</param> /// <param name="w">圖片寬</param> /// <param name="newwidth">flash中縮放后的寬,不是繪制在圖片上忽略</param> /// <returns></returns> protected PointF[] GetPointFs(List<float[]> data, bool IsImg, float h, float w, float newwidth) { float top = IsImg ? 25 : 0, scale = IsImg ? w / newwidth : 1;//坐標點縮放比率,不是圖片忽略此設置 List<PointF> points = new List<PointF>(); foreach (float[] d in data) { points.Add(new PointF(d[0] * scale, (d[1] - top) * scale)); } return points.ToArray(); } public void ProcessRequest(HttpContext context) { string img = context.Request.Form["img"], w = context.Request.Form["w"], h = context.Request.Form["h"] , drawdata = context.Request.Form["drawdata"], newwidth = context.Request.Form["newwidth"] , fn = DateTime.Now.ToString("yyyyMMddHHmmssfff") + "." + context.Request.Form["ext"];//新文件名 Regex rxInt = new Regex(@"^/d+$", RegexOptions.Compiled); List<DrawData> data = (List<DrawData>)JsonConvert.DeserializeObject(drawdata, typeof(List<DrawData>)); Bitmap bm; bool IsImg = false; float fW = 0, fH = 0, fNewWidth = 0; if (!string.IsNullOrEmpty(img) && File.Exists(context.Server.MapPath(img))) {//存在圖片 bm = new Bitmap(context.Server.MapPath(img)); IsImg = true; fW = bm.Width; fH = bm.Height; if (!string.IsNullOrEmpty(newwidth) && rxInt.IsMatch(newwidth)) fNewWidth = float.Parse(newwidth); else fNewWidth = fW; } else { fW = !string.IsNullOrEmpty(w) && rxInt.IsMatch(w) ? float.Parse(w) : 650; fH = !string.IsNullOrEmpty(h) && rxInt.IsMatch(h) ? float.Parse(h) : 400; bm = new Bitmap((int)fW, (int)fH); } Color color = Color.White; using (Graphics g = Graphics.FromImage(bm)) { foreach (DrawData d in data) { color = Color.FromArgb(d.alpha, ColorTranslator.FromHtml("#" + d.color)); using (Pen pen = new Pen(color, d.lw)) { g.DrawLines(pen, GetPointFs(d.data, IsImg, fH, fW, fNewWidth)); } } } bm.Save(context.Server.MapPath(fn)); bm.Dispose(); context.Response.Write("{success:true,fn:'" + fn + "',xsc:'" + ((float)fW / (float)fNewWidth).ToString() + "|" + newwidth + "'}"); } public bool IsReusable { get { return false; } }}
新聞熱點
疑難解答
圖片精選