最近项目中要用到直尺,可以用类写,但是不能图视化编辑刻度,感觉不爽。好在想到可以借助扩展Flash的api来写一个绘画扩展工具,画钟盘特爽!!!希望对大家有帮助。
效果图:
图标Ruler.png:
下面是Ruler.jsfl的源代码:
/* * 刻度绘画工具 * 2.0 支持直线和圆形,椭圆形 * * 3.0 * 增加绘画时把起点作为中心点 * 改善画圆形时的操作方式 * * Directed by kiwiw3 */ var LINE = "直线"; var CIRCLE = "圆形"; var STARTPOINT = "起点"; var CENTERPOINT = "中心"; var style = LINE; var startPointMode = STARTPOINT; var thePolygon = new Array; var theStroke=new Array(); var didDrag = false; var startPt = new Object; var cell = 6; var leftMar = 0; var upSign = false;//文本在刻度的上方 var offsetLine = 10;//文本与刻度线的距离 var showZeroLine=true;//显示刻度基准线 var lineRoles = []; var shotcut = new Array(4); function configureTool() { theTool = fl.tools.activeTool; theTool.setToolName("ruler"); theTool.setIcon("Ruler.png"); theTool.setMenuString("刻度工具"); theTool.setToolTip("刻度工具"); theTool.setOptionsFile( "Ruler.xml" ); theTool.setPI( "shape" ); var folder = fl.configURI+"Tools/"; var str = FLfile.read(folder+"RulerData.txt"); if(str){ eval("lineRoles =["+str+"]"); } str = FLfile.read(folder+"RulerSettingData.txt"); if(str){ var arr = str.split("\n"); var l = arr.length; if(l==5){ style = arr[0]; startPointMode = arr[1]; cell = Number(arr[2]); showZeroLine = parseInt(arr[3])==1?true:false; upSign = parseInt(arr[4])==1?true:false; } } } function analyShutcut(str){ var arr = str.split("+"); var isctrl = false; var isshift = false; var isalt = false; var key = 0; for(var itm in arr){ var itmval = arr[itm].replace(/\s/g,"").toUpperCase(); if(itmval=="CTRL"){ isctrl=true; }else if(itmval=="SHIFT"){ isshift=true; }else if(itmval=="ALT"){ isalt=true; }else if(itmval){ key = itmval.charCodeAt(0); } } shotcut[0]=isctrl shotcut[1]=isshift shotcut[2]=isalt shotcut[3]=key str = ""; if(isctrl){ str+="ctrl "; } if(isshift){ if(str){ str +=" + "; } str+="shift"; } if(isalt){ if(str){ str +=" + "; } str+="alt"; } if(key){ if(str){ str +=" + "; } str+=String.fromCharCode(key); } //fl.trace(str) var url = fl.configURI+"Tools/Ruler.xml"; if(FLfile.exists(url)){ var estr = FLfile.read(url); estr = findAndReplace(estr,'defaultValue="','" type',str); FLfile.remove(url); FLfile.write(url,estr); } } function notifySettingsChanged() { theTool = fl.tools.activeTool; analyShutcut(theTool.shotcut); } function setCursor() { fl.tools.setCursor( 0 ); } function activate() { var theTool = fl.tools.activeTool analyShutcut(theTool.shotcut); } function keyUp() { var l=shotcut.length; var showUI=true; if(shotcut[0]!=fl.tools.ctlIsDown){ showUI=false; } if(shotcut[1]!=fl.tools.shiftIsDown){ showUI=false; } if(shotcut[2]!=fl.tools.altIsDown){ showUI=false; } if(shotcut[3]!=fl.tools.getKeyDown()){ showUI=false; } if(showUI){ startPt=null; thePolygon.length=0; var folder = fl.configURI+"Tools/"; saveRoleSettingFile(folder+"RulerSettingUI.xml"); var obj = fl.getDocumentDOM().xmlPanel(folder+"RulerSettingUI.xml"); if (obj.dismiss == "accept") { cell = Number(obj.cell);//parseInt(obj.cell); if(isNaN(cell)){ cell = 6; } style = obj.style; startPointMode = obj.startPointMode; showZeroLine = (obj.showZeroLine=="true"?true:false); upSign = (obj.upSign=="true"?true:false); //解释刻度规则 eval("var tempRoles=["+obj.lineRolesStr+"]"); if(tempRoles instanceof Array ){ var l=tempRoles.length; var arr=[] for(var i=0;i<l;i++){ var itm = tempRoles[i]; if(itm.len&&itm.gap){ arr.push(itm) } } lineRoles = arr; saveRulerData(folder+"RulerData.txt"); } saveRulerSettingData(folder+"RulerSettingData.txt"); saveRoleSettingFile(folder+"RulerSettingUI.xml"); } } } function obj2label(obj){ var str = ""; for(var kk in obj){ if(kk!="dismiss"){ var val = obj[kk]; if(val||val===0){ if(str){ str +="," }else{ str +="{" } str += kk+":" if((typeof val)== "string" && isNaN(val)){ str +='"'+val+'"'; }else{ str +=val; } } } } str +="}" return str; } function saveRulerData(url){ if(FLfile.exists(url)){ FLfile.remove(url); } var l = lineRoles.length; var rolestr=""; for(var i=0;i<l;i++){ var itm = lineRoles[i] if(rolestr){ rolestr+=","; } rolestr +=obj2label(itm); } FLfile.write(url,rolestr); } function saveRulerSettingData(url){ if(FLfile.exists(url)){ FLfile.remove(url); } var cstr=""; cstr += style+"\n"; cstr += startPointMode+"\n"; cstr += cell+"\n"; cstr += (showZeroLine?1:0)+"\n"; cstr += (upSign?1:0);//+"\n" FLfile.write(url,cstr); } function saveRoleSettingFile(settingui){ if(FLfile.exists(settingui)){ var str = FLfile.read(settingui); if(style == LINE){ str = findAndReplace(str,'value="直线"','/>',' selected = "true" '); str = findAndReplace(str,'value="圆形"','/>',' '); }else if(style == CIRCLE){ str = findAndReplace(str,'value="直线"','/>',' '); str = findAndReplace(str,'value="圆形"','/>',' selected = "true" '); } if(startPointMode == STARTPOINT){ str = findAndReplace(str,'value="起点"','/>',' selected = "true" '); str = findAndReplace(str,'value="中心"','/>',' '); }else if(startPointMode == CENTERPOINT){ str = findAndReplace(str,'value="起点"','/>',' '); str = findAndReplace(str,'value="中心"','/>',' selected = "true" '); } str = findAndReplace(str,'id="cell" value="','" />',cell); str = findAndReplace(str,'id="showZeroLine" checked="','" />',showZeroLine?'true':'false'); str = findAndReplace(str,'id="upSign" checked="','" />',upSign?'true':'false'); var rolestr = "\n"; var l = lineRoles.length; for(var i=0;i<l;i++){ var itm = lineRoles[i] itm.listIndex = i; rolestr +=" <listitem label='"+obj2label(itm)+"' />\n"; } str = findAndReplace(str,'<listbox id ="lineRolesList" rows ="6" value="1" width="300">',' </listbox>',rolestr); rolestr = ""; l = lineRoles.length; for(var i=0;i<l;i++){ var itm = lineRoles[i] if(rolestr){ rolestr+=","; } rolestr +="{label:'"+obj2label(itm)+"'}"; } str = findAndReplace(str,'var mainRoles = [',']',rolestr); FLfile.remove(settingui); FLfile.write(settingui,str); } } function findAndReplace(data,stamark,endmark,str){ var pos = data.indexOf(stamark); if(pos!=-1){ var pos2 = data.indexOf(endmark,pos); if(pos2!=-1){ var part1 = data.substr(0,pos+stamark.length); var part2 = data.substr(pos2); data = part1+str+part2; return data; } } return null; } function mouseDown() { didDrag = false; fl.drawingLayer.beginDraw(); startPt = fl.tools.snapPoint( fl.tools.penDownLoc ); } function buildPolygonObjLine( pt1, pt2, thePolygon ) { var radian = get2PRadian(pt1.x,pt1.y,pt2.x,pt2.y); var distance=fl.Math.pointDistance(pt1, pt2); if(startPointMode==CENTERPOINT){ pt1 = {x:pt2.x-distance*2*Math.cos(radian),y:pt2.y-distance*2*Math.sin(radian)}; distance=fl.Math.pointDistance(pt1, pt2); } var index=0; if (showZeroLine) { thePolygon[0] = pt1.x; thePolygon[1] = pt1.y; thePolygon[2] = pt2.x; thePolygon[3] = pt2.y; index+=4; } var directV = upSign?-1:1; var l = Math.floor(distance/cell);//总刻度数 for (var i = 0; i <= l; i++) { var ll = lineRoles.length; var drawFlag=false; var len=0; var len2=0; var stroke=null; for (var ii = 0; ii < ll; ii++) { var itm=lineRoles[ii]; if((i%itm.gap)==0){ stroke = itm; len=itm.len; if(itm.nelen){ len2=itm.nelen; } drawFlag=true; } } if(drawFlag){ var posX = leftMar + i * cell; var point = polar(posX, radian); point.x += pt1.x; point.y += pt1.y; var role = polar(len*directV,radian+Math.PI/2); var role2 = polar(len2*directV,radian+Math.PI/2); thePolygon[index] = point.x+role2.x; thePolygon[index+1] = point.y+role2.y; thePolygon[index+2] = point.x+role.x; thePolygon[index+3] = point.y+role.y; theStroke[index/4]=stroke; index+=4; } } thePolygon.length=index; theStroke.length=index/4; } function buildPolygonObjCircle( pt1, pt2, thePolygon,start_radian ) { var radian = get2PRadian(pt1.x,pt1.y,pt2.x,pt2.y); var distance=fl.Math.pointDistance(pt1, pt2); if(startPointMode==CENTERPOINT){ pt1 = {x:pt2.x-distance*2*Math.cos(radian),y:pt2.y-distance*2*Math.sin(radian)}; distance=fl.Math.pointDistance(pt1, pt2); } var index=0; thePolygon[0] = pt1.x; thePolygon[1] = pt1.y; thePolygon[2] = pt2.x; thePolygon[3] = pt2.y; index+=4; var directV = upSign?-1:1; var dx = pt2.x - pt1.x; var dy = pt2.y - pt1.y; var a = (pt2.x-pt1.x)/2; var b = (pt2.y-pt1.y)/2; if (a < 0) a = -a; if (b < 0) b = -b; if(dx<0){ var cx = pt2.x+a; }else{ var cx = pt1.x+a; } if(dy<0){ var cy = pt2.y+b; }else{ var cy = pt1.y+b; } var cellRadian = cell*Math.PI/180; var l = Math.floor(Math.PI*2/(cellRadian));//总刻度数 for (var i = 0; i <= l; i++) { var ll = lineRoles.length; var drawFlag=false; var len=0; var len2=0; var stroke=null; for (var ii = 0; ii < ll; ii++) { var itm=lineRoles[ii]; if((i%itm.gap)==0){ stroke = itm; len=itm.len; if(itm.nelen){ len2=itm.nelen; } drawFlag=true; } } if(drawFlag){ var r = i*cellRadian+start_radian; var xx = cx+a*Math.cos(r); var yy = cy+b*Math.sin(r); r = get2PRadian(xx,yy,cx,cy); var role = polar(len*directV,r); var role2 = polar(len2*directV,r); thePolygon[index] = xx+role2.x; thePolygon[index+1] = yy+role2.y; thePolygon[index+2] = xx+role.x; thePolygon[index+3] = yy+role.y; theStroke[index/4]=stroke; index+=4; } } thePolygon.length=index; theStroke.length=index/4; } function transformPoint( pt, mat ) { var x = pt.x*mat.a + pt.y*mat.c + mat.tx; var y = pt.x*mat.b + pt.y*mat.d + mat.ty; pt.x = x; pt.y = y; } function drawPolygonObj( thePolygon ) { if (thePolygon.length != 0) { var tmpPt = new Object; var viewMat = fl.getDocumentDOM().viewMatrix; var index = 3; switch(style){ //case LINE: //break; case CIRCLE: var tmpPt2 = new Object; tmpPt.x = thePolygon[index-3]; tmpPt.y = thePolygon[index-2]; transformPoint(tmpPt, viewMat); tmpPt2.x = thePolygon[index-1]; tmpPt2.y = thePolygon[index]; transformPoint(tmpPt2, viewMat); var dx=(tmpPt2.x-tmpPt.x)/2; var dy=(tmpPt2.y-tmpPt.y)/2; var cx=(tmpPt2.x+tmpPt.x)/2; var cy=(tmpPt2.y+tmpPt.y)/2; fl.drawingLayer.moveTo(cx-2, cy); fl.drawingLayer.lineTo(cx+3, cy); fl.drawingLayer.moveTo(cx, cy-2); fl.drawingLayer.lineTo(cx, cy+3); if(showZeroLine){ fl.drawingLayer.moveTo(tmpPt2.x,cy); var tanV = Math.tan(Math.PI / 8); var sinV = Math.sin(Math.PI / 4) fl.drawingLayer.curveTo(tmpPt2.x,tanV * dy + cy,sinV * dx + cx,sinV * dy + cy); fl.drawingLayer.curveTo(tanV * dx + cx,tmpPt2.y,cx,tmpPt2.y); fl.drawingLayer.curveTo(-tanV * dx + cx,tmpPt2.y,-sinV * dx + cx,sinV * dy + cy); fl.drawingLayer.curveTo(tmpPt.x,tanV * dy + cy,tmpPt.x,cy); fl.drawingLayer.curveTo(tmpPt.x,-tanV * dy + cy,-sinV * dx + cx,-sinV * dy + cy); fl.drawingLayer.curveTo(-tanV * dx + cx,tmpPt.y,cx,tmpPt.y); fl.drawingLayer.curveTo(tanV * dx + cx,tmpPt.y,sinV * dx + cx,-sinV * dy + cy); fl.drawingLayer.curveTo(tmpPt2.x,-tanV * dy + cy,tmpPt2.x,cy); } index=7; break; } while (index < thePolygon.length) { tmpPt.x = thePolygon[index-3]; tmpPt.y = thePolygon[index-2]; transformPoint(tmpPt, viewMat); fl.drawingLayer.moveTo( tmpPt.x, tmpPt.y ); tmpPt.x = thePolygon[index-1]; tmpPt.y = thePolygon[index]; transformPoint(tmpPt, viewMat); fl.drawingLayer.lineTo(tmpPt.x, tmpPt.y); index += 4; } } } function get2PRadian(x1, y1, x2, y2) { var Y = y2-y1; var X = x2-x1; if (X == 0) { if (Y<0) { return Math.PI*3/2; } else { return Math.PI/2; } } var tan = Y/X; var radian = Math.atan(tan); //弧度 radian = X>=0 ? Y<0 ? radian+Math.PI*2 : radian : radian+Math.PI; return (radian); } function polar(len,radian){ return {x:len*Math.cos(radian),y:len*Math.sin(radian)} } function drawRuler(pt1,pt2) { var dx = pt2.x - pt1.x; var dy = pt2.y - pt1.y; var abs_dx = dx; var abs_dy = dy; if (dx < 0) abs_dx = -dx; if (dy < 0) abs_dy = -dy; if (!(abs_dx > 2 || abs_dy > 2)) { return; } switch(style){ case LINE: if (fl.tools.shiftIsDown) { var angle = get2PRadian(pt1.x,pt1.y,pt2.x,pt2.y)*180/Math.PI; if(angle<30){ pt2.y = pt1.y; }else if(angle<60){ pt2.y = pt1.y+pt2.x-pt1.x; }else if(angle<120){ pt2.x = pt1.x; }else if(angle<150){ pt2.y = pt1.y+pt1.x-pt2.x; }else if(angle<210){ pt2.y = pt1.y; }else if(angle<240){ pt2.y = pt1.y-(pt1.x-pt2.x); }else if(angle<300){ pt2.x = pt1.x; }else if(angle<330){ pt2.y = pt1.y-(pt2.x-pt1.x); }else if(angle<360){ pt2.y = pt1.y; } } buildPolygonObjLine(pt1, pt2, thePolygon); break; case CIRCLE: var ori_radian = get2PRadian(pt1.x,pt1.y,pt2.x,pt2.y);; if (fl.tools.shiftIsDown) { var d =fl.Math.pointDistance(pt1, pt2); var r45=45*Math.PI/180 pt2.x = pt1.x+d*Math.cos(r45); pt2.y = pt1.y+d*Math.cos(r45); } buildPolygonObjCircle(pt1, pt2, thePolygon,ori_radian); break; } didDrag = true; fl.drawingLayer.beginFrame(); drawPolygonObj( thePolygon ); fl.drawingLayer.endFrame(); } function mouseMove(mouseLoc) { if (fl.tools.mouseIsDown && startPt) { var pt1 = startPt; var pt2 = fl.tools.snapPoint( mouseLoc ); pt1 = {x:pt1.x,y:pt1.y}; pt2 = {x:pt2.x,y:pt2.y}; drawRuler(pt1,pt2); } } function polygonToPath( thePolygon ) { var index = 3; switch(style){ //case LINE: //break; case CIRCLE: var path = fl.drawingLayer.newPath(); var tmpPt = new Object; var tmpPt2 = new Object; //画圆心十字 tmpPt.x = thePolygon[index-3]; tmpPt.y = thePolygon[index-2]; tmpPt2.x = thePolygon[index-1]; tmpPt2.y = thePolygon[index]; var dx=(tmpPt2.x-tmpPt.x)/2; var dy=(tmpPt2.y-tmpPt.y)/2; var cx=(tmpPt2.x+tmpPt.x)/2; var cy=(tmpPt2.y+tmpPt.y)/2; path.addPoint(cx-2, cy); path.addPoint(cx+2, cy); path.newContour(); path.addPoint(cx, cy-2); path.addPoint(cx, cy+2); //画圆 if(showZeroLine){ var tx =Math.sin(Math.PI / 4) * dx + cx var ty =Math.sin(Math.PI / 4) * dy + cy; var ttx =-Math.sin(Math.PI / 4) * dx + cx var tty =-Math.sin(Math.PI / 4) * dy + cy; var tanV = Math.tan(Math.PI / 8); path.newContour(); path.addCurve(tmpPt2.x,cy,tmpPt2.x,tanV * dy + cy,tx,ty); path.addCurve(tx,ty,tanV * dx + cx,tmpPt2.y,cx,tmpPt2.y); path.addCurve(cx,tmpPt2.y,-tanV * dx + cx,tmpPt2.y,ttx,ty); path.addCurve(ttx,ty,tmpPt.x,tanV * dy + cy,tmpPt.x,cy); path.addCurve(tmpPt.x,cy,tmpPt.x,-tanV * dy + cy,ttx,tty); path.addCurve(ttx,tty,-tanV * dx + cx,tmpPt.y,cx,tmpPt.y); path.addCurve(cx,tmpPt.y,tanV * dx + cx,tmpPt.y,tx,tty); path.addCurve(tx,tty,tmpPt2.x,-tanV * dy + cy,tmpPt2.x,cy); }; path.makeShape(); index=7; break; } var path = fl.drawingLayer.newPath(); var doc = fl.getDocumentDOM() var ostroke = doc.getCustomStroke("toolbar"); while (index < thePolygon.length) { var stroke=theStroke[(index-3)/4]; var seted=false; if(stroke){ var cstroke = doc.getCustomStroke("toolbar"); if(stroke.color&&stroke.color!=ostroke.color){ cstroke.color = stroke.color; seted=true; } if(stroke.thickness&&stroke.thickness!=ostroke.thickness){ cstroke.thickness = stroke.thickness; seted=true; } if(stroke.style&&stroke.style!=ostroke.style){ cstroke.style = stroke.style; seted=true; } if(seted){ //在有修改的情况下,设置笔触 doc.setCustomStroke(cstroke); } } if(seted){ var tmppath = fl.drawingLayer.newPath(); tmppath.addPoint( thePolygon[index-3], thePolygon[index-2] ); tmppath.addPoint( thePolygon[index-1], thePolygon[index] ); tmppath.makeShape(true); //恢复原来笔触 doc.setCustomStroke(ostroke); }else{ path.newContour(); path.addPoint( thePolygon[index-3], thePolygon[index-2] ); path.addPoint( thePolygon[index-1], thePolygon[index] ); } index += 4; } path.makeShape(true); } function mouseUp() { fl.drawingLayer.endDraw(); if (didDrag) { polygonToPath( thePolygon ); } startPt=null; thePolygon.length=0; }
当然还需要另外的Ruler.xml文件
<properties> <property name="设置面板快捷键(手动输入): " variable="shotcut" defaultValue="x" type="String"/> </properties>
做了个自动安装Ruler插件到Flash默认工具目录中的setup.jsfl
/* *Ruler 自动安装包 *Directed by kiwiw3 */ fl.outputPanel.clear(); var folder = fl.configURI+"Tools"; var folder1= fl.scriptURI; fl.trace(folder); var data =FLfile.read(folder+"/toolConfig.xml"); var files=["Ruler.jsfl","Ruler.png","Ruler.xml","RulerSettingUI.xml","RulerData.txt"];//所需文件清单 var fsta = folder1.lastIndexOf("/"); folder1 =folder1.substr(0,fsta); var l=files.length for(var i=0;i<l;i++){ var url = folder+"/"+files[i] if(FLfile.exists(url)){ FLfile.remove(url); } var result = FLfile.copy(folder1+"/"+files[i],url); if(result){ fl.trace("复制"+files[i]+"成功") }else{ fl.trace("复制"+files[i]+"失败") data=""; break; } } function findAndInsert(data,findstr,insertstr){ var pos = data.indexOf(findstr); if(pos!=-1){ var part1 = data.substr(0,pos); var part2 = data.substr(pos); data = part1+insertstr+part2; return data; } return null; } //将Ruler插入到扩展工具xml文件 if(data){ var insertnode = '<tool name = "ruler"/>'; var fsta = data.indexOf(insertnode); if(fsta==-1){ var ndata = findAndInsert(data,'<tool name = "pencil"/>',insertnode+"\r\n"); if(ndata){ //fl.trace(ndata); }else{ ndata = findAndInsert(data,'</group>',insertnode+"\r\n"); if(ndata){ //fl.trace(ndata); } } if(ndata){ FLfile.write(folder+"/toolConfig.xml",ndata); } } fl.trace("Ruler 安装完成。"); fl.reloadTools(); }else{ fl.trace("Ruler 安装失败。"); }
我已经上传到新浪共享资料,可供下载