现有系统的流程图要重构,把之前的插件剔除。
找了很多画流程图的方式,但最后还是选择使用原生的canvas来画。

大概效果就是这样:


步骤:

  1. 最重要的就是数据源,数据源给好了,画起来就很方便了。下边是部分测试数据源。
        var res = { "Result": 0, "Error": "", "ResultString": "{\"items\":[{\"drawtype\":\"ellipse\",\"drawdata\":{\"data\":{\"color\":\"#000000\",\"style\":\"Solid\",\"cap\":\"round\",\"fill\":\"#5D9969\",\"borderWidth\":1,\"type\":\"ellipse\",\"cx\":284.0,\"cy\":36.0,\"rx\":61.0,\"ry\":30.0,\"fillcolor\":\"#5D9969\"},\"stencilType\":\"ellipse\",\"id\":\"oval_node0000\",\"node_key\":\"\",\"flowid\":\"PLAN_ORDER0001089935\",\"clickable\":0,\"emp_name\":\"\"},\"set_flag\":0.0},{\"drawtype\":\"rect\",\"drawdata\":{\"data\":{\"color\":\"#000000\",\"style\":\"Solid\",\"cap\":\"round\",\"fill\":\"#C1FFC1\",\"borderWidth\":1,\"type\":\"rect\",\"x\":219.0,\"y\":100.0,\"width\":131.0,\"height\":75.0,\"r\":5.0,\"fillcolor\":\"#C1FFC1\"},\"stencilType\":\"rect\",\"id\":\"rr_node0001\",\"node_key\":\"NODE0001\",\"flowid\":\"PLAN_ORDER0001089935\",\"clickable\":0,\"emp_name\":\"\"},\"set_flag\":0.0},{\"drawtype\":\"rect\",\"drawdata\":{\"data\":{\"color\":\"#000000\",\"style\":\"Solid\",\"cap\":\"round\",\"fill\":\"#FF9900\",\"borderWidth\":1,\"type\":\"rect\",\"x\":219.0,\"y\":200.0,\"width\":131.0,\"height\":75.0,\"r\":5.0,\"fillcolor\":\"#FF9900\"},\"stencilType\":\"rect\",\"id\":\"rr_node0007\",\"node_key\":\"NODE0007\",\"flowid\":\"PLAN_ORDER0001089935\",\"clickable\":0,\"emp_name\":\"\"},\"set_flag\":0.0},{\"drawtype\":\"rect\",\"drawdata\":{\"data\":{\"color\":\"#000000\",\"style\":\"Solid\",\"cap\":\"round\",\"fill\":\"#FFF68F\",\"borderWidth\":1,\"type\":\"rect\",\"x\":220.0,\"y\":298.0,\"width\":131.0,\"height\":75.0,\"r\":5.0,\"fillcolor\":\"#FFF68F\"},\"stencilType\":\"rect\",\"id\":\"rr_node0002\",\"node_key\":\"NODE0002\",\"flowid\":\"PLAN_ORDER0001089935\",\"clickable\":0,\"emp_name\":\"\"},\"set_flag\":0.0}]}", "FlowID": "PLAN_ORDER0001089935", "OrderState": "09", "IsTemplate": 0, "IsEdit": 1 }var items = JSON.parse(res.ResultString).items;
  1. 设计出画各种图形的函数
    圆角矩形和椭圆都是特殊的图形格式,根据自身的需要可以再选择添加其他图形的函数。
     // 填字function drawText(ctx, item) {ctx.fillStyle = item.color;ctx.font = "12px sans-serif";ctx.textAlign = "center";ctx.textBaseline = "top";//填充字符串var txt = item.text;var x = item.x;var y = item.y;ctx.fillText(txt, x, y);}// 画线function drawLine(ctx, item) {var lx = item.x1;var ly = item.y1;var mx = item.x2;var my = item.y2;ctx.beginPath();// 初始地ctx.moveTo(mx, my);// 目的地ctx.lineTo(lx, ly);ctx.stroke();}// 画圆角矩形function drawRoundRect(ctx, x, y, w, h, item, radius) {radius = radius || 20;ctx.beginPath();ctx.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 3 / 2);ctx.lineTo(w - radius + x, y);ctx.arc(w - radius + x, radius + y, radius, Math.PI * 3 / 2, Math.PI * 2);ctx.lineTo(w + x, h + y - radius);ctx.arc(w - radius + x, h - radius + y, radius, 0, Math.PI * 1 / 2);ctx.lineTo(radius + x, h + y);ctx.arc(radius + x, h - radius + y, radius, Math.PI * 1 / 2, Math.PI);ctx.closePath();ctx.fillStyle = item.color ? (item.color.bgColor ? item.color.bgColor : 'rgba(91,155,213,0.5)') : 'white'; //背景颜色ctx.fill();ctx.strokeStyle = item.color ? (item.color.borderColor ? item.color.borderColor : '#5B9BD5') : '#5B9BD5'; //边框颜色if (item.text) {ctx.font = 'normal 14px 微软雅黑';ctx.fillStyle = item.color ? (item.color.fontColor ? item.color.fontColor : '#5B9BD5') : '#5B9BD5'; //文字颜色ctx.textAlign = "center";ctx.fillText(item.text, x + w / 2, y + h / 2 + 6);}ctx.stroke();}// 画椭圆function EvenCompEllipse(ctx, item) {var x = item.x, y = item.y,a = item.w, b = item.h;ctx.save();//选择a、b中的较大者作为arc方法的半径参数var r = (a > b) ? a : b;var ratioX = a / r; //横轴缩放比率var ratioY = b / r; //纵轴缩放比率ctx.scale(ratioX, ratioY); //进行缩放(均匀压缩)ctx.beginPath();//从椭圆的左端点开始逆时针绘制ctx.moveTo((x + a) / ratioX, y / ratioY);ctx.arc(x / ratioX, y / ratioY, r, 0, 2 * Math.PI);ctx.closePath();ctx.stroke();ctx.fillStyle=item.color.bgColor || "#9bcd9b";ctx.fill();ctx.restore();};
  1. 给元素添加事件
    canvas是一个画布没法锁定某个元素,所以使用坐标范围来判断是否是某个元素内部。
    例如:点击某个位置,是循环数据源,判断当前点击的坐标,在不在坐标范围内。如果在某个范围内则代表是点击了该元素。
        // 每个对象的坐标范围function calRange(obj) {var newObj;if (obj.type == "rect" || obj.type == "text") {newObj = {minX: obj.x,maxX: obj.x + obj.width,minY: obj.y,maxY: obj.y + obj.height}}return newObj;}// 给所有图形添加事件function addMethod(c, items) {//给所有图形添加点击事件c.onclick = function (ev) {var ev = ev || window.event;var ua = navigator.userAgent.toLowerCase();var isIE = ua.indexOf("compatible") > -1 && ua.indexOf("msie") > -1 && !ua.indexOf("opera") > -1; //IE浏览器var isEdge = ua.indexOf("Edge") > -1;var isIE11 = ua.toLowerCase().match(/rv:([\d.]+)\) like gecko/);var curx = (isIE || isEdge || isIE11) ? ev.offsetX : ev.layerX;var cury = (isIE || isEdge || isIE11) ? ev.offsetY : ev.layerY;console.log(curx);console.log(cury);for (var i = 0; i < items.length; i++) {// var e = items[i];var edata = items[i].drawdata.data;var range = edata.range;if (edata.type == "rect") {if (curx >= range.minX && curx <= range.maxX && cury >= range.minY && cury <= range.maxY) {console.log('点击块的内部了哦!');}}}}
  1. 初始化canvas对象,循环画元素。
     var c = document.getElementById("myCanvas");var ctx = c.getContext("2d");// x坐标, y坐标, 宽, 高console.log(items);var canvasHeight = 0; //高度var canvasWidth = 0; //宽度// 循环得到高度 找到x, y坐标最大的元素作为宽度和高度for (var i = 0; i < items.length; i++) {var e = items[i];var mhight = 0;var mwidth = 0;if (e.drawtype == "ellipse") {mhight = e.drawdata.data.cy + (e.drawdata.data.ry * 2);mwidth = e.drawdata.data.cx + (e.drawdata.data.rx * 2);} else if (e.drawtype == "rect") {mhight = e.drawdata.data.y + e.drawdata.data.height;mwidth = e.drawdata.data.x + e.drawdata.data.width;} else {continue;}canvasHeight = (canvasHeight > mhight) ? canvasHeight : mhight;canvasWidth = (canvasWidth > mwidth) ? canvasWidth : mwidth;};c.height = (typeof (canvasHeight) == "number") ? (canvasHeight + 10) : 2000;c.width = (typeof (canvasWidth) == "number") ? (canvasWidth + 10) : 1600;for (var i = 0; i < items.length; i++) {var e = items[i];var edata = items[i].drawdata.data;if (e.drawtype == "rect") {var xr = edata.x;var yr = edata.y;var wr = edata.width;var hr = edata.height;items[i].drawdata.data.range = calRange(edata);var item = {color: {bgColor: edata.fill,borderColor: edata.color,fontColor: "#000000",},text: ""}drawRoundRect(ctx, xr, yr, wr, hr, item, 10);};if (e.drawtype == "ellipse") {var xe = edata.cx;var ye = edata.cy;var we = edata.rx;var he = edata.ry;var item = {color: {bgColor: edata.fill,borderColor: edata.color,fontColor: "#000000",},text: "",x: edata.cx,y: edata.cy,w: edata.rx,h: edata.ry}EvenCompEllipse(ctx, item);}if (e.drawtype == "line") {var item = {x1: edata.x1,y1: edata.y1,x2: edata.x2,y2: edata.y2,}drawLine(ctx, item);}if (e.drawtype == "text") {items[i].drawdata.data.x = edata.x + 5;items[i].drawdata.data.y = edata.y + 5;// items[i].drawdata.data.range = calRange(edata);var item = {x: edata.x,y: edata.y,height: edata.height,width: edata.width,color: edata.color,fill: edata.fill,text: edata.text};drawText(ctx, item);}}addMethod(c, items);

canvas笔记:

  1. canvas元素高度变化会使元素清空,这点可以作为快捷清空画布的方法,但是也固定了代码顺序。
  2. 划线的时候moveTo要写在lineTo的前面,虽然线显示起来没有方向,但是canvas画起来有方向。
  3. 椭圆的时候虽然可以直接用ellipse方法但是此方法只有谷歌兼容,就没必要使用了。
  4. canvas方法只能在canvas元素上使用,在div上会报错。。。

canvas画流程图相关推荐

  1. html css画流程图,css canvas 绘制流程图(1)

    //1.引入js //画流程图 //画所有的图形:画图和画对应的箭头 function drawFlowChart(context, canvas, flowdata, initTop, initSp ...

  2. activiti前端画图转化_activiti在线画流程图

    springboot2.2 activiti6.0 activiti-modeler 5.22.0 注明:版本不一样会导致报错 效果图 代码分享: 链接:https://pan.baidu.com/s ...

  3. G6实现标签拖动连线画流程图

    需求描述 列出所有的task标签,拖动task标签在一旁画流程图,打包task的任务名及id和任务的执行流程以json的格式发给后端. 技术栈 G6,vue,h5自带的draggable实现拖动.也稍 ...

  4. 在Markdown中用mermaid画流程图和ER图

    # 在Markdown中用mermaid画流程图 mermaid支持三种图形的绘制, 分别是流程图, 时序图和甘特图, 本篇文章只介绍了mermaid中流程图在markdown的使用. 流程图方向有下 ...

  5. 流程图的制作技巧分享,手把手教你如何画流程图?

    什么是流程图?流程图是思维导图的一种表现形式,流程图是流经一个系统的信息流.观点流或部件流的图形代表.在企业中,流程图主要用来说明某一过程.这种过程既可以是生产线上的工艺流程,也可以是完成一项任务必需 ...

  6. startuml如何画流程图_因为流程图没画好SCI被拒稿!看完师姐的攻略后我被吊打了!...

    写SCI论文常常会遇到一个问题:对自己的研究很熟悉,但是如何把自己的研究过程介绍给读者则不是一件那么容易的事情.如果不能让读者了解研究过程,读者会对研究结果是否合理.如何应用存在疑问:尤其是期刊编辑和 ...

  7. 微信小程序中base64格式的小程序码通过canvas画出来无效

    使用场景 小程序中的文章详情页面有一个分享功能:用户点击分享按钮,生成一张分享图片(包括封面图,简介以及带有文章ID的小程序码),方便用户保存在本地. 问题说明 小程序码通过后台接口获取,格式如下:' ...

  8. 关于星空的java小程序_[Java教程]小程序使用Canvas画饼图_星空网

    小程序使用Canvas画饼图 2018-10-24 0 先上效果图 -------------------------------------------------------------w --- ...

  9. vision画流程图的软件_产品流程图的定义,作用和画法

    流程图和产品文档以及原型图一样,都是日常产品工作中经常用来表达业务逻辑和产品逻辑的载体,这一小节主要从三个方面介绍流程图的相关知识,分别是:1.基本定义(what):流程图是什么:2.为什么要画(wh ...

最新文章

  1. python输出价目表-Python:使用基于事件驱动的SAX解析XML
  2. c语言地理坐标存储 转发,纬度/经度坐标的2个列表之间的地理距离
  3. 与afreez一起学习DirectFB之:一个linux下的framebuffer例子的学问
  4. 2015 跨年博文总结
  5. 《C++ Primer第五版》第一章-------IO机制和注释缩进
  6. 软件测试要求太高,软件“故障门”频现 对软件测试提出更高要求
  7. Java基础01 1个和2个区别比较
  8. 微服务自动化部署(ansible playbook)干货之--zookeeper部署
  9. 个人博客 修改markdown代码块背景颜色
  10. matlab编写LDA,lda算法matlab实现
  11. ectouch v1 thinkphp的搜索问题
  12. ubantu 安装火狐浏览器插件
  13. js通过开始时间和结束时间计算出中间的所有日期
  14. GATK RNA-Seq Snps Indel 分析
  15. 查找python array索引
  16. Linux(Ubuntu 22.04)学习笔记——让虚拟机共享主机上的文件夹
  17. JAVA自学-day13-StringBuffer类、数组高级以及Arrays、Integer类
  18. 起底野蛮成长的腾讯共享wifi赚钱小程序,到底是机遇还是陷阱?
  19. linux输入特殊符号密码,Linux-shell操作环境和通配符及特殊符号
  20. Pycharm、Vscode设置美女背景【内附20张高清图片】

热门文章

  1. windows下安装 swoole
  2. word在另外计算机格式不对,【2人回答】Word在别人电脑里排版不一样。如何解决?-3D溜溜网...
  3. 向量化算法 word2vec
  4. prtitlecreator下载_PrTitleCreator最新版
  5. 尚吉ipad点菜机及餐饮管理系统
  6. 离线linux下python安装pip包_Linux pip命令和在线、离线安装
  7. tomcat启动失败的原因、JAVA_HOME配置失败的几种原因、另一种启动tomcat服务器的方式catalina run
  8. 为什么有些人的Macbook没有装OSX??
  9. HTML-table标签属性
  10. 2014年10月26完美世界校招java中的两道java题