/* * 专门负责导出流程图文件并让用户下载的扩展包方法 */ ;(function ( global, factory ) { 'use strict'; if ( typeof define !== 'undefined' && define.amd ) { // export as AMD... define( ['jquery','GooFlow'], factory ); } else if ( typeof module !== 'undefined' && module.exports ) { // ...or as browserify factory( require('jquery'), require('GooFlow') ); }else factory( global.$, global.GooFlow ); }( typeof window !== 'undefined' ? window : this, function ( $,GooFlow ) { if(GooFlow.prototype.exportDiagram && typeof GooFlow.prototype.exportDiagram==='function'){ return;//防止多次载入 } var Cmder = { //构建背景 initBg : function(width,height,bgColor){ var canvas = document.createElement('canvas'); canvas.width = width; canvas.height = height; var ctx = canvas.getContext('2d'); if(bgColor) ctx.fillStyle = bgColor; ctx.fillRect(0,0,canvas.width,canvas.height); ctx.save(); return canvas; }, _toNum: function(str){ return str!==null&&str!==''? parseInt(str.split('px')[0],10):undefined; }, _analyseLabel: function(labelDom){ var tagName = labelDom[0].tagName; var offsetLeft = labelDom[0].offsetLeft; var offsetTop = labelDom[0].offsetTop; if(tagName==='TD'){ offsetLeft += labelDom.children("div")[0].offsetLeft; offsetTop += labelDom.children("div")[0].offsetTop; } var lineHeight = this._toNum(labelDom.css("line-height")); var fontSize = labelDom.css('font-size'); return { font: fontSize+' '+labelDom.css('font-family'), fontSize: this._toNum(fontSize.split("px")[0]), text: labelDom.text(),//文字内容 color: labelDom.css('color'),//文字颜色 width: labelDom[0].offsetWidth,//文字容器宽度 height: labelDom[0].offsetHeight,//文字容器高度 lineHeight:lineHeight, offsetLeft:offsetLeft, offsetTop:offsetTop, lineNum: Math.ceil(labelDom[0].offsetHeight/lineHeight)//文字要分几行? }; }, _analyseIcon: function(iconDom){ var bgImg = iconDom.css("background-image"); var property={ // top: this._toNum(iconDom[0].style.top),// // left: this._toNum(iconDom[0].style.left),// offsetLeft:iconDom[0].offsetLeft, offsetTop:iconDom[0].offsetTop, width: iconDom.width(), height: iconDom.height() }; if(bgImg && bgImg!=='none'){//CSS SPITE背景图式 bgImg = bgImg.replace(/"/g,"").split("url(")[1]; property.backgroundImage=bgImg.substr(0,bgImg.length-1);//图标背景图 bgImg = iconDom.css("background-position").split(" "); property.pX = parseFloat(bgImg[0].split("px")[0])*-1;//图标背景定位X property.pY = parseFloat(bgImg[1].split("px")[0])*-1;//图标背景定位Y }else{//矢量图标字体式 $.extend(property,{ font: iconDom.css('font-size')+' '+iconDom.css('font-family').split(' ')[0],//图标矢量字体库 lineHeight : this._toNum(iconDom.css('line-height')),//图标矢量字体行高 color: iconDom.css('color'),//图标矢量字体颜色 opacity: parseFloat(iconDom.css("opacity")),//图标矢量透明度 content:window.getComputedStyle(iconDom[0],'::before').getPropertyValue('content') }); } return property; }, _analyseArea : function(areaDom){ var bg=areaDom.children(".bg"); return { top: this._toNum(areaDom[0].style.top), left: this._toNum(areaDom[0].style.left), width: areaDom.outerWidth(), height: areaDom.outerHeight(), borderColor: bg.css('border-top-color'),//区域边框颜色 bgColor: bg.css('background-color'),//区域块背景色 opacity: parseFloat(bg.css("opacity")),//区域块透明度 icon: this._analyseIcon(areaDom.children('i')), label: this._analyseLabel(areaDom.children("label")) }; }, _analyseNode : function(nodeDom){ var property={ top: this._toNum(nodeDom[0].style.top),// left: this._toNum(nodeDom[0].style.left),// width: nodeDom.outerWidth(),// height: nodeDom.outerHeight(),// borderColor: nodeDom.css('border-top-color'),//节点边框颜色 borderWidth: this._toNum(nodeDom.css('border-top-width')),//节点边框宽度 bgColor: nodeDom.css('background-color'),//节点背景色 borderRadius: this._toNum(nodeDom.css("border-top-left-radius")),//节点圆角半径 boxShadow: nodeDom.css("box-shadow"),//节点阴影 icon: this._analyseIcon(nodeDom.find('i')) }; if(nodeDom.hasClass("item_round")){ property.label = this._analyseLabel(nodeDom.children(".span")); }else{ property.label = this._analyseLabel(nodeDom.children("table").find("td:eq(1)")); } return property; }, _fillIcon:function(canvas, bgLeft,bgTop,icon, bgImage){ var ctx = canvas.getContext('2d'); if(icon.backgroundImage===undefined){//矢量字体图标 if(icon.content.indexOf('"')===0){ icon.content = icon.content.split('"')[1]; } icon.color = icon.color.replace('rgb', 'rgba').replace(')', ', ' + icon.opacity + ')'); ctx.fillStyle = icon.color; ctx.font = icon.font; ctx.textAlign='center'; ctx.textBaseline='middle'; // 绘制内容 ctx.fillText(icon.content, bgLeft+icon.offsetLeft+4+icon.width/2, bgTop+icon.offsetTop+4+icon.height/2); return null; }else{//css spite背景定位图标 var tmpX=0,tmpY=0; if(icon.pX<0){ tmpX-=icon.pX; icon.pX=0; } if(icon.pY<0){ tmpY-=icon.pY; icon.pY=0; } //console.log(icon.pX+','+icon.pY); ctx.drawImage(bgImage, icon.pX, icon.pY, icon.width, icon.height, bgLeft+icon.offsetLeft+4+tmpX, bgTop+icon.offsetTop+4+tmpY, icon.width, icon.height ); } }, _fillLabel: function(canvas, bgLeft, bgTop, label) { var ctx = canvas.getContext('2d'); ctx.fillStyle = label.color; ctx.textAlign='center'; ctx.font = label.font; ctx.textBaseline='top'; var str=label.text; var lineWidth = 0;//某一行字的实际宽度 var lastSubStrIndex= 0; //每次开始截取的字符串的索引 var hack = (window.ActiveXObject || "ActiveXObject" in window)? 1:0; var x = bgLeft+label.offsetLeft+label.width/2+hack/2;//文字(可能有多行)的x坐标 var y = bgTop+label.offsetTop+hack;//某一行文字(可能有多行)的y坐标 if(navigator.userAgent.indexOf('Firefox')>=0){ y += (label.lineHeight-label.fontSize); } for(var i=0;i= label.width ){ ctx.fillText(str.substring(lastSubStrIndex,i),x,y);//绘制截取部分 y+=label.lineHeight; lineWidth=0; lastSubStrIndex=i; } }else{//绘制剩余部分 ctx.fillText(str.substring(lastSubStrIndex,i+1),x,y); } } }, //根据区域组信息在背景上画一堆区域组泳道(传参areas为要绘制的区域组详细json信息) renderAreas:function(canvas,areas, iconBgImage){ var ctx = canvas.getContext('2d'); for(var key in areas) { var area = areas[key]; //填充半透明矩形 area.bgColor = area.bgColor.replace('rgb', 'rgba').replace(')', ', ' + area.opacity + ')'); area.borderColor = area.borderColor.replace('rgb', 'rgba').replace(')', ', ' + area.opacity + ')'); ctx.fillStyle = area.bgColor; ctx.strokeStyle = area.borderColor; ctx.rect(area.left, area.top, area.width, area.height); ctx.fill(); ctx.stroke(); this._fillIcon(canvas, area.left-3, area.top-3, area.icon, iconBgImage); this._fillLabel(canvas, area.left, area.top, area.label); } }, //根据节点信息在背景上画一组节点(传参nodes为要绘制的节点详细json信息) renderNodes:function(canvas,nodes,iconBgImage){ var ctx = canvas.getContext('2d'); var imgLoadFuncs=[]; for(var key in nodes){ var node = nodes[key]; //渲染阴影 var sd = node.boxShadow.split(") "); if(sd.length===1){ var tmp = node.boxShadow.split("rgba"); sd[0]='rgba'+tmp[1]; sd[1]=tmp[0]; } ctx.shadowColor = sd[0]; sd=sd[1].split(" "); ctx.shadowOffsetX=this._toNum(sd[0])+(node.borderWidth>1? 1:0); ctx.shadowOffsetY=this._toNum(sd[1])+(node.borderWidth>1? 1:0); ctx.shadowBlur=this._toNum(sd[2]); //填充圆角矩形 ctx.fillStyle=node.bgColor; ctx.roundRect( node.left+node.borderWidth/2, node.top+node.borderWidth/2, node.width-node.borderWidth, node.height-node.borderWidth, node.borderRadius).fill(); //加边框 ctx.shadowBlur=0; ctx.shadowColor=''; ctx.shadowOffsetX=0; ctx.shadowOffsetY=0; ctx.strokeStyle = node.borderColor; ctx.lineWidth = (node.borderWidth===0? 0.01:node.borderWidth); ctx.stroke(); this._fillIcon(canvas, node.left, node.top+(node.borderRadius>6? 1:0), node.icon, iconBgImage); this._fillLabel(canvas, node.left, node.top, node.label); } return imgLoadFuncs; }, _analyseLine:function(lineDom){ //only for IE var fontFamily = $(".GooFlow").css("font-family"); //基本样式 var path = lineDom.childNodes[1]; var property={ color: path.getAttribute("stroke"),//箭头则用fill lineWidth: path.getAttribute("stroke-width"),//线条宽度箭头的strokeWidth为0 lineCap: 'round' }; var style = path.style.strokeDasharray; property.lineDash=(style && style!=null); //文字 var text=lineDom.childNodes[2]; var fontColor = text.getAttribute("fill"); if(!fontColor||fontColor===null||fontColor===''){ fontColor='#777'; } property.label={ text: text.textContent, font: text.style.fontSize+' '+fontFamily, color: fontColor, left:text.getAttribute("x"), top:text.getAttribute("y") }; //获取连线从首至尾各个点的坐标值 var d = path.getAttribute("d"); var tmp = d.substring(2,d.length).split("L"); var points=[];//连线中各点集合 for(var i=0;i-1){//当为IE11及以下版本浏览器时,使用Canvg第三方工具 var lineEl={}; for(var key in Goo.$lineDom){ lineEl[key]=Cmder._analyseLine(Goo.$lineDom[key]); } //console.log(lineEl); Cmder.renderLines(canvas,lineEl); try{ var blob = canvas.msToBlob(); navigator.msSaveBlob(blob, fileName+".png"); } catch(e){ //生成一个下载链接并点击 var base64 = canvas.toDataURL('image/png'); //将画布内的信息导出为png图片数据 $('body').append(''); var oPop=window.open("",'_blank'); for (; oPop.document.readyState !== "complete";) { if (oPop.document.readyState === "complete") break; } oPop.document.write(''+fileName+'.png'); } }else{ var strSvg = '' +'' + $("#draw_"+Goo.$id).html() +''; //COPY连线内容 var image = new Image(); image.src='data:image/svg+xml,'+ encodeURIComponent(strSvg); image.onload=function(){ ctx.drawImage(image, 0, 0); var a = document.createElementNS("http://www.w3.org/1999/xhtml", "a"); a.href = canvas.toDataURL('image/png'); //将画布内的信息导出为png图片数据 a.download = fileName+".png"; //设定下载名称 document.body.appendChild(a); a.click(); //点击触发下载 document.body.removeChild(a); }; } }; // 如果图片已经存在于浏览器缓存,直接调用回调函数 if(!iconImage || iconImage.complete|| (!!window.ActiveXObject||"ActiveXObject" in window) ) { tempFunc(); return;// 直接返回,不用再处理onload事件 } iconImage.onload=function(){ tempFunc(); }; } }));