Joint.js实现流程图

     因为工作需要在网页上实现流程图,不经意间发现了JointJS。JointJS是一款功能强大的图形可视化交互工具,可用来开发流程图,思维导图等复杂图形交互应用。废话不多说,直接上代码:


官网:https://resources.jointjs.com/demos


1、引入js,需要注意引入顺序

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone.js"></script>

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jointjs/2.2.1/joint.min.js"></script>

2、创建画布及画板

const graph = new joint.dia.Graph; // 创建画板,所有图上的元素都在画板里 var paper = new joint.dia.Paper({ // 创建画板上的画布,画布是用来渲染画板 el: document.getElementById('myGraph'), // 指向HTML里ID为"myGraph"的元素 model: graph, // 指定画板 width: 1500, // 画布宽600像素 height: 300, // 画布高100像素 gridSize: 1, // 画布上元素拖动时步进的像素,默认1,设的高方便对齐 background: { // 画布背景色 color: 'rgba(0, 0, 0, 0.1)' }, interactive :true //元素是否可拖动 });

3、Joint.js的图形元素

       常见的图形如:矩形(Rectangle),多边形(Polygon),圆(Circle),椭圆(Ellipse)外,还可以插入图片(BorderedImage)等

// 创建一个矩形 var rect = new joint.shapes.standard.Rectangle(); rect.position(100, 30); // 矩形左上角的位置,x:100,y:30,单位像素 rect.resize(100, 40); // 矩形大小,宽100,高40,单位像素 rect.attr({ body: { fill: 'blue' // 填充色 }, label: { text: 'Hello', // 矩形上显示的文字 fill: 'white' // 文字颜色 } }); list.push(rect) rect.addTo(graph); // 将上面定义的矩形加入到画板中 alertText(rect); //自定义的改变元素显示内容的方法 var rect2 = rect.clone(); // 复制一个相同的矩形 rect2.translate(300, 0); // 将矩形在水平方向上向右移动300像素 rect2.attr('label/text', 'World!'); // 设置矩形2上的文字 rect2.addTo(graph); // 将矩形2加入到画板中 alertText(rect2) list.push(rect2); addArraw(rect, rect2) //将两个元素连接起来//创建一个椭圆var ellipse = new joint.shapes.standard.Ellipse(); ellipse.resize(100, 50); ellipse.position(100, 30); ellipse.attr('root/title', 'joint.shapes.standard.Ellipse'); ellipse.attr('label/text', 'Ellipse'); ellipse.attr('body/fill', 'lightblue'); ellipse.addTo(graph); ellipse.translate(200*(6-count), 0); ellipse.addTo(graph)//引入图片示例rect = new joint.shapes.standard.BorderedImage(); rect.resize(120, 100); rect.position(100, 30); rect.attr('root/title', 'joint.shapes.standard.BoarderedImage'); rect.attr('label/text', dataList[i].title+'\n'+dataList[i].name+'\n'+dataList[i].time); rect.attr('border/rx', 5); rect.attr('border/stroke','green') //设置边框颜色 rect.attr('border/stroke-width','3') rect.attr('image/xlinkHref', 'test.png');//元素中嵌入图片

rect = new joint.shapes.standard.EmbeddedImage(); rect.resize(120, 108); rect.position(125, 110); rect.attr('root/title', 'joint.shapes.standard.EmbeddedImage'); rect.attr('label/text', dataList[i].title+'\n'+dataList[i].name+'\n'+dataList[i].time); rect.attr('label/fill','white') rect.attr('label/refX','10px') rect.attr('image/xlinkHref', 'img/image.png'); rect.attr('image/x', '0px'); rect.attr('image/y', '0px'); rect.attr('image/refWidth', '100%'); rect.attr('image/refHeight', '100%'); rect.attr('image/preserveAspectRatio','xMidYMid'); //默认xMidYMin rect.addTo(graph);

4、连线

//定义连线的方法function addArraw(source, target) { link(source, target, "");}//定义连线 function link(source, target, label){ var cell = new joint.shapes.standard.Link({ source: { id: source.id }, target: { id: target.id }, labels: [{ position: 0.5, attrs: { text: { text: label || '', 'font-weight': 'bold', 'font-size': '12px' } } }], router: { name: 'manhattan' },//设置连线弯曲样式 'normal' - 普通线 'orthogonal' - 基础版的正交折线 'manhattan' - 优化版的正交折线 'metro' - 另一种正交折线 'oneSide' attrs: { '.connection': { stroke: '#C0D8FD',//连线颜色 }, '.marker-target': { fill: '#C0D8FD',//箭头颜色 d: 'M 20 -10 0 0 20 10 Z'//箭头样式 }, line: { stroke: '#4649F4', // SVG attribute and value 'stroke-width': 6,//连线粗细 // 'stroke-dasharray':"2 2" } } }); // if(list[2] == source){ // cell.set('vertices', [ // { x: 620, y: 55 },{ x: 625, y: 60 }, // ] // } //定义连线必须经过的点 // cell.attr('line/stroke-dasharray','5 2') //虚线,每隔5像素简单2像素 graph.addCell(cell); return cell;}

5、demo全

<!DOCTYPE html><html> <head> <meta charset="utf-8"> <title></title> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone.js"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jointjs/2.2.1/joint.min.js"></script> </head> <body> <button onclick="addRectangle()">添加矩形</button> <button onclick="addEllipse()">添加椭圆</button> <span id="Tips"></span> <input id="alertText" style="display: none;" type="text" onchange="changeText()"/> <!-- 这里是画布 --> <div id="myGraph"></div> </body> <script type="text/jscript"> const graph = new joint.dia.Graph; // 创建画板,所有图上的元素都在画板里 var paper = new joint.dia.Paper({ // 创建画板上的画布,画布是用来渲染画板 el: document.getElementById('myGraph'), // 指向HTML里ID为"myGraph"的元素 model: graph, // 指定画板 width: 1500, // 画布宽600像素 height: 400, // 画布高100像素 gridSize: 1, // 画布上元素拖动时步进的像素,默认1,设的高方便对齐 background: { // 画布背景色 color: 'rgba(0, 0, 0, 0.1)' }, interactive :true //图形元素是否可拖动 }); const list = []; let count; var obj; var code; // var code2 = $("input[id='alertText']").val(); document.getElementById("alertText").addEventListener("keydown", function(event) { if (event.keyCode==13){ obj.attr('label/text', code) } }); function changeText(){ code = $("#alertText").val(); obj.attr('label/text', code) } function addRectangle() { if(count > 1){ // 创建一个矩形 let rect = new joint.shapes.standard.Rectangle(); rect.position(100, 30); // 矩形左上角的位置,x:100,y:30,单位像素 rect.resize(100, 40); // 矩形大小,宽100,高40,单位像素 rect.attr({ body: { fill: 'red' // 填充色 }, label: { text: 'new', // 矩形上显示的文字 fill: 'white' // 文字颜色 } }); rect.translate(200*(6-count), 0); rect.addTo(graph) addArraw(list[list.length - 1], rect); alertText(rect) list.push(rect) count--; if(count==1){ addArraw(rect,list[0]); } } } function addEllipse() { if(count > 1){ var ellipse = new joint.shapes.standard.Ellipse(); ellipse.resize(100, 50); ellipse.position(100, 30); ellipse.attr('root/title', 'joint.shapes.standard.Ellipse'); ellipse.attr('label/text', 'Ellipse'); ellipse.attr('body/fill', 'lightblue'); ellipse.addTo(graph); ellipse.translate(200*(6-count), 0); ellipse.addTo(graph) addArraw(list[list.length - 1], ellipse); alertText(ellipse) list.push(ellipse) count--; if(count==1){ addArraw(ellipse,list[0]); } } } window.onload=function() { //模拟后端传入数据 var dataList = [{ title:"开立医嘱", name:"张三", time:"2020-12-18 00:00:00" },{ title:"药师审方", name:"李四", time:"2020-12-18 00:00:00" },{ title:"处方缴费", name:"王麻子", time:"2020-12-18 00:00:00" },{ title:"药房摆药", name:"康康", time:"2020-12-18 00:00:00" },{ title:"药房发药", name:"李雷", time:"2020-12-18 00:00:00" }] var data = [{ title:"开立医嘱", name:"张三", time:"2020-12-18 00:00:00" },{ title:"药师审方", name:"李四", time:"2020-12-18 00:00:00" },{ title:"处方缴费", name:"王麻子", time:"2020-12-18 00:00:00" }] let flag = true; //是否闭环 count = 5; // 循环创建 for(var i=0;i<dataList.length;i++){ var rect; rect = new joint.shapes.standard.EmbeddedImage(); rect.resize(180, 70); rect.position(80, 110); rect.attr('root/title', 'joint.shapes.standard.EmbeddedImage'); rect.attr('label/text', ' '+dataList[i].title+'\n' +' '+dataList[i].name+'\n' +dataList[i].time); rect.attr('label/fill','#3E3E3E') rect.attr('label/refX','1%') rect.attr('body/stroke','#2E78F6') rect.attr('image/xlinkHref', 'img/bg01.png'); rect.attr('image/x', '0px'); rect.attr('image/y', '0px'); rect.attr('image/refWidth', '100%'); rect.attr('image/refHeight', '100%'); rect.attr('image/preserveAspectRatio','xMidYMid'); //默认xMidYMin rect.addTo(graph); rect.translate(250*i, 0); for(var j=0;j<data.length;j++){ if(JSON.stringify(data[j])===JSON.stringify(dataList[i])){ rect.attr('image/xlinkHref', 'img/bg02.png'); rect.attr('label/fill','#2E78F6') } } rect.addTo(graph); if(i!=0 && i!=dataList.length){ addArraw(list[list.length - 1], rect); } if(i == dataList.length-2){ rect.translate(-250, 200); } if(flag&&i==dataList.length-1){ rect.translate(-1000, 200); addArraw(rect,list[0]) } alertText(rect); list.push(rect) } } function addArraw(source, target) { // 创建一条连线 link(source, target, ""); } //定义连线 function link(source, target, label){ var cell = new joint.shapes.standard.Link({ source: { id: source.id }, target: { id: target.id }, labels: [{ position: 0.5, attrs: { text: { text: label || '', 'font-weight': 'bold', 'font-size': '12px' } } }], router: { name: 'manhattan' },//设置连线弯曲样式 'normal' - 普通线 'orthogonal' - 基础版的正交折线 'manhattan' - 优化版的正交折线 'metro' - 另一种正交折线 'oneSide' attrs: { '.connection': { stroke: '#C0D8FD',//连线颜色 }, '.marker-target': { fill: '#C0D8FD',//箭头颜色 d: 'M 20 -10 0 0 20 10 Z'//箭头样式 }, line: { stroke: '#4649F4', // SVG attribute and value 'stroke-width': 6,//连线粗细 // 'stroke-dasharray':"2 2" } } }); graph.addCell(cell); return cell; } function alertText(rect){ paper.findViewByModel(rect).on('cell:pointerclick', function() { // var code = prompt("请输入我爱你:"); var elem = document.getElementById("alertText"); elem.setAttribute('style', 'display: block'); elem.setAttribute('style', 'position: absolute'); elem.setAttribute('style', 'left: 500px'); elem.setAttribute('style', 'top: 1000px'); elem.setAttribute('style', 'z-index: 10'); obj = rect; for(let i=0;i<list.length;i++){ if(list[i] == rect){ $("#Tips").html("请修改步骤"+(i+1)+"的值") $("#alertText").focus(); } } }); } </script></html>

6.结果展示


©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Data Visualization with D3 D3: SVG中的jQurey 1. Add Documen...
    王策北阅读 906评论 0 2
  • HTML 5 HTML5概述 因特网上的信息是以网页的形式展示给用户的,因此网页是网络信息传递的载体。网页文件是用...
    阿啊阿吖丁阅读 5,107评论 0 0
  • graphviz 画流程图 brew install graphvizvi lz.dot dot -Tjpg lz...
    神刀阅读 3,721评论 0 0
  • 今天的工作重点分三块: 属性窗口,用于展示和修改单个节点的属性值 Run to here(RTH)功能,任意选择一...
    敬亭阁主阅读 2,844评论 3 3
  • 久违的晴天,家长会。 家长大会开好到教室时,离放学已经没多少时间了。班主任说已经安排了三个家长分享经验。 放学铃声...
    飘雪儿5阅读 8,064评论 16 22

友情链接更多精彩内容