流程图(HTML5拖拽)
1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <title>Document</title> 7 <style type="text/css"> 8 #d1 { 9 width: 800px; 10 height: 800px; 11 border: 1px solid #ccc; 12 position: relative; 13 background: #fafafa; 14 } 15 16 #d1>div { 17 width: 130px; 18 height: 30px; 19 border: 1px solid #ccc; 20 border-radius: 8px; 21 position: absolute; 22 z-index: 2; 23 text-align: center; 24 line-height: 30px; 25 background: #fff; 26 } 27 28 #d1>svg { 29 width: 100%; 30 height: 100%; 31 position: absolute; 32 z-index: 1 33 } 34 35 .input .point { 36 position: absolute; 37 border: 6px solid transparent; 38 border-top: 6px solid #ccc; 39 top: 0px; 40 left: 58px; 41 } 42 43 .input .circle { 44 position: absolute; 45 width: 10px; 46 height: 10px; 47 border: 1px solid #ccc; 48 top: -7px; 49 left: 60px; 50 border-radius: 50%; 51 background: #fff; 52 } 53 54 .output .circle { 55 position: absolute; 56 width: 15px; 57 height: 15px; 58 border: 1px solid #ccc; 59 bottom: -10px; 60 left: 57px; 61 border-radius: 50%; 62 background: #fff; 63 cursor: crosshair; 64 z-index: 10; 65 } 66 67 .output .circle:hover { 68 background: #FC9901; 69 } 70 </style> 71 </head> 72 73 <body> 74 <ul class="shuiguo"> 75 <li draggable="true" data-name="ps1">ps1</li> 76 <li draggable="true" data-name="ps2">ps2</li> 77 <li draggable="true" data-name="ps3">ps3</li> 78 <li draggable="true" data-name="ps4">ps4</li> 79 <li draggable="true" data-name="switch">switch</li> 80 </ul> 81 <div id="d1"> 82 <svg> 83 84 </svg> 85 </div> 86 <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script> 87 <script type="text/javascript"> 88 var dragData = []; 89 //重置拖拽后流程图展示 90 function reload(isend) { 91 $(function() { 92 var html = ""; 93 var g = ` 94 <defs> 95 <marker id="markerArrow1" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth"> 96 <path d="M0,1 L0,5 L3,3 z" fill="#CCCCCC"></path> 97 </marker> 98 <marker id="markerArrow2" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth"> 99 <path d="M0,1 L0,5 L3,3 z" fill="#cccdff"></path> 100 </marker> 101 <marker id="markerArrow3" markerWidth="10" markerHeight="10" refX="3" refY="2.6" orient="auto" markerUnits="strokeWidth"> 102 <path fill="#f00" d="m6.75848,4.22161c-0.13193,0.12924 -0.3468,0.12924 -0.47903,0l-3.03436,-2.97252c-0.13193,-0.12953 -0.13223,-0.33974 0,-0.46927c0.13163,-0.12953 0.3465,-0.12953 0.47933,0l3.03406,2.97223c0.13193,0.13012 0.13253,0.34003 0,0.46956l0,0l0,0zm-0.00361,-2.974l-3.03406,2.97223c-0.13253,0.12983 -0.3471,0.12983 -0.47933,0c-0.13223,-0.12924 -0.13223,-0.33915 0.0003,-0.46927l3.03406,-2.97193c0.13253,-0.12953 0.3474,-0.12953 0.47903,-0.0003c0.13253,0.12953 0.13193,0.33974 0,0.46927l0,0l0,0z"/> 103 </marker> 104 </defs> 105 `; 106 if($('svg').siblings()) { //清除$('svg')范围外的所有元素 107 var prev = $('svg').siblings(); 108 for(var i = 0; i < prev.length; i++) { 109 prev[i].remove(); 110 } 111 } 112 console.log(dragData); 113 for(var i = 0; i < dragData.length; i++) { //循环dragData,重置流程图所有dom节点 114 if(dragData[i] != undefined) { 115 var data = dragData[i]; 116 html += 117 ` 118 <div class = "${data.name}" data-drag="1" data-id = "${data.id}" data-inx = "${data.inx}" data-iny = "${data.iny}" data-label = "${data.label}" ondragstart = "insideDrag(this)" draggable = "true" style = "transform:translate(${data.x}px,${data.y}px)"> 119 <span class = "${data.icon}" data-id = "${data.id}"></span> 120 <span data-id = "${data.id}">${data.label}</span> 121 <div class = "output"> 122 <span class = "circle" title = "输出" onmousedown = "noDrag(this)" onmouseup = "addDrag(this)" onmouseleave = "draw(this)" onmouseenter = "noMove()" data-id = "${data.id}"></span> 123 </div> 124 </div> 125 ` 126 if(data.link.length > 0) { 127 for(var j = 0; j < data.link.length; j++) { 128 g += 129 ` 130 <g id="${data.link[j].name}"> 131 <path style="cursor:pointer" d = "M${data.outx} ${data.outy} Q${data.link[j].mx1} ${data.link[j].my1} ${data.link[j].mx2} ${data.link[j].my2} T${data.link[j].dx} ${data.link[j].dy}" stroke = "#CCCCCC" fill = "none" stroke-width="4" marker-end="url(#markerArrow1)"/> 132 </g> 133 ` 134 } 135 } 136 } 137 } 138 $('svg').before(html); 139 $('svg').html(g); 140 if(isend) { 141 $('svg').on('mouseenter', "path", function() { 142 $(this).attr({ 143 "stroke": "#cccdff", 144 "marker-end": "url(#markerArrow2)", 145 "marker-mid": "url(#markerArrow3)" 146 }) 147 }).on('mouseleave', "path", function() { 148 $(this).attr({ 149 "stroke": "#cccccc", 150 "marker-end": "url(#markerArrow1)", 151 "marker-mid": "" 152 }) 153 }).on('click', "path", function() { 154 var $p = $(this).parent(); 155 var id = $p[0].id; 156 for(var i = 0; i < dragData.length; i++) { 157 var data = dragData[i]; 158 for(var j = 0; j < data.link.length; j++) { 159 if(id == data.link[j].name) { 160 data.link.splice(j, 1) 161 } 162 } 163 for(var j = 0; j < data.linked.length; j++) { 164 if(id == data.linked[j].name) { 165 data.linked.splice(j, 1) 166 } 167 } 168 } 169 $p.remove() 170 }); 171 } else { 172 $('svg').off('mouseenter mouseleave', "path"); 173 } 174 console.log($('svg').siblings()); 175 }) 176 } 177 //reload(); 178 document.getElementById('d1').ondragover = function(e) { 179 e.preventDefault(); //流程图展示区阻止默认事件 180 } 181 var dWidth = Number($('#d1').css('width').slice(0, -2)); //流程图展示区域宽度 182 console.log(dWidth); 183 var dHeight = Number($('#d1').css('height').slice(0, -2)); //流程图展示区域高度 184 console.log(dHeight); 185 var dClient = $("#d1").offset().top; //流程图展示区偏移位置top 186 var dLeft = $("#d1").offset().left; //流程图展示区偏移位置left 187 console.log('顶部位置', dClient); 188 console.log('左边位置', dLeft); 189 190 //模块拖进流程图后,初始化拖拽方法 191 /* 192 * word:模块名称 193 * name:模块数据名称 194 * type:拖拽事件类型,用于判断来执行不同拖拽事件,"outside":拖拽完成,"inside":开始拖拽 195 * id:模块id 196 */ 197 function drag(word, name, type, id) { 198 console.log(type); 199 console.log(name); 200 //在可拖动元素放置在 <div> 元素中时执行事件ondrop 201 document.getElementById('d1').ondrop = function(e) { 202 var sTop = $(document).scrollTop(); //文档滚动条偏移量top 203 var sLeft = $(document).scrollLeft(); //文档滚动条偏移量left 204 console.log('e.target', e.target.dataset.id); 205 var x, y; 206 console.log('e.clientX', e.clientX); 207 console.log('e.clientY', e.clientY); 208 if((dWidth - e.clientX + dLeft + 65) - sLeft >= 132) { 209 x = e.clientX - 65 - dLeft + sLeft; 210 } else { 211 x = dWidth - 133; 212 } 213 if((e.clientX - dLeft) < 65) { 214 x = 1; 215 } 216 if((dHeight - e.clientY + dClient + 15) - sTop >= 33) { 217 y = e.clientY - 15 - dClient + sTop; 218 } else { 219 y = dHeight - 33; 220 } 221 if(e.clientY - 15 - dClient + sTop < 0) { 222 y = 1; 223 } 224 if(type == "outside") { 225 console.log('放下了'); 226 dragData.push({ 227 id: dragData.length, 228 label: word, 229 name: name, 230 x: x, //模块相对展示区域的位移x 231 y: y, //模块相对展示区域的位移y 232 outx: x + 68, //模块输出点位置x/贝塞尔曲线起点x 233 outy: y + 30, //模块输出点位置y/贝塞尔曲线起点y 234 inx: x + 65, //模块输入点位置x 235 iny: y - 1, //模块输入点位置y 236 link: [], //存放由该模块连接的关联线数据数组 237 linked: [], //存放由其他模块连接该模块的关联线数据数组 238 dx: 0, 239 dy: 0, 240 mx1: 0, 241 my1: 0, 242 mx2: 0, 243 my2: 0, 244 style: name, 245 draw: false, 246 icon: name + "Icon" 247 }); 248 console.log(dragData); 249 reload(1); 250 } 251 if(type == "inside") { 252 console.log(word, name, type, id); 253 for(var i = 0; i < dragData.length; i++) { 254 if(id == dragData[i].id) { 255 dragData[i].x = x; 256 dragData[i].y = y; 257 dragData[i].outx = dragData[i].x + 68; 258 dragData[i].outy = dragData[i].y + 30; 259 dragData[i].inx = dragData[i].x + 65; 260 dragData[i].iny = dragData[i].y - 1; 261 console.log('dragData[i].link', dragData[i].link); 262 for(let j = 0; j < dragData[i].link.length; j++) { 263 dragData[i].link[j].linkId = parseFloat(dragData[i].link[j].name.split("|")[1]); 264 } 265 for(var k = 0; k < dragData[i].linked.length; k++) { 266 console.log('dragData[i].linked[k]', dragData[i].linked[k]); 267 for(let j = 0; j < dragData.length; j++) { 268 if(dragData[i].linked[k].linkedNum == dragData[j].id) { 269 console.log('ID一样了啊'); 270 for(let m = 0; m < dragData[j].link.length; m++) { 271 if(dragData[i].linked[k].name == dragData[j].link[m].name) { 272 console.log("名字一样了啊"); 273 dragData[j].link[m].dx = dragData[i].inx; 274 dragData[j].link[m].dy = dragData[i].iny-10; 275 dragData[j].link[m].mx1 = dragData[j].outx; 276 dragData[j].link[m].my1 = dragData[j].link[m].dy > dragData[j].outy ? dragData[j].outy + (dragData[j].link[m].dy - dragData[j].outy) / 3 : dragData[j].outy - (dragData[j].link[m].dy - dragData[j].outy) / 3; 277 dragData[j].link[m].mx2 = dragData[j].outx + (dragData[j].link[m].dx - dragData[j].outx) / 2, 278 dragData[j].link[m].my2 = dragData[j].outy + (dragData[j].link[m].dy - dragData[j].outy) / 2 279 } 280 } 281 } 282 } 283 } 284 if(dragData[i].link.length > 0) { 285 for(var j = 0; j < dragData[i].link.length; j++) { 286 dragData[i].link[j].mx1 = dragData[i].outx; 287 dragData[i].link[j].my1 = dragData[i].link[j].dy > dragData[i].outy ? dragData[i].outy + (dragData[i].link[j].dy - dragData[i].outy) / 3 : dragData[i].outy - (dragData[i].link[j].dy - dragData[i].outy) / 3; 288 dragData[i].link[j].mx2 = dragData[i].outx + (dragData[i].link[j].dx - dragData[i].outx) / 2, 289 dragData[i].link[j].my2 = dragData[i].outy + (dragData[i].link[j].dy - dragData[i].outy) / 2 290 } 291 } 292 } 293 } 294 reload(1); 295 } 296 } 297 } 298 var shuiguo = $('.shuiguo li'); 299 var isondrag = 0; 300 console.log(shuiguo); 301 for(var i = 0; i < shuiguo.length; i++) { 302 console.log(shuiguo[i]); 303 shuiguo[i].ondragstart = function() { 304 console.log('东完了') 305 drag(this.innerHTML, this.dataset.name, 'outside'); 306 } 307 } 308 309 function insideDrag(item) { 310 console.log(item); 311 if(item.getAttribute('draggable')) { 312 drag(item.dataset.label, item.className, 'inside', item.dataset.id); 313 } 314 } 315 316 function noDrag(item) { 317 event.preventDefault(); 318 event.stopPropagation(); 319 console.log(item.parentNode.parentNode); 320 var parent = item.parentNode.parentNode; 321 parent.setAttribute('draggable', false); 322 for(var i = 0; i < dragData.length; i++) { 323 for(var d = 0; d < dragData[i].link.length; d++) { 324 if(!~dragData[i].link[d].name.indexOf("|")) { 325 dragData[i].link.splice(d, 1) 326 } 327 } 328 if(parent.dataset.id == dragData[i].id) { 329 dragData[i].draw = true; 330 dragData[i].link.push({ 331 name: parent.dataset.id + parent.className, 332 dx: 0, 333 dy: 0, 334 mx1: 0, 335 my1: 0, 336 mx2: 0, 337 my2: 0 338 }); 339 $('body').on('mouseup', function(e) { 340 for(var j = 0; j < dragData.length; j++) { 341 if(parent.dataset.id == dragData[j].id) { 342 console.log('页面抬起了'); 343 dragData[j].draw = false; 344 var $dom = $(e.target).data("drag") ? $(e.target) : $(e.target).closest("div[data-drag]"); 345 if($dom.length) { 346 if($dom.data("drag") && $dom[0].dataset.id != dragData[j].id) { //判断是否关联另外模块,非自己 347 $('svg').unbind('mousemove'); 348 var name = dragData[j].link[dragData[j].link.length - 1].name + "|" + $dom[0].dataset.id + $dom[0].className; 349 var isontbe = 0; //判断是否存在关联 350 for(let i = 0; i < dragData.length; i++) { 351 if($dom[0].dataset.id == dragData[i].id) { 352 for(let c = 0; c < dragData[i].linked.length; c++) { 353 if(name == dragData[i].linked[c].name) { 354 isontbe = 1 355 } 356 } 357 if(!isontbe) { //不存在时候存入linked 358 dragData[i].linked.push({ 359 name: name, 360 linkedNum: parseFloat(name) 361 }) 362 } 363 } 364 } 365 if(!isontbe) { //不存在时候生成link数据 366 dragData[j].link[dragData[j].link.length - 1].name = name; 367 dragData[j].link[dragData[j].link.length - 1].dx = Number($dom[0].dataset.inx); 368 dragData[j].link[dragData[j].link.length - 1].dy = Number($dom[0].dataset.iny)-10; 369 } else { 370 dragData[j].link.splice(dragData[j].link.length - 1, 1); 371 } 372 } else { 373 dragData[j].link.splice(dragData[j].link.length - 1, 1); 374 } 375 } else { 376 dragData[j].link.splice(dragData[j].link.length - 1, 1); 377 } 378 $('svg').unbind('mousemove'); 379 reload(1); 380 } 381 } 382 $('body').unbind('mouseup'); 383 }) 384 //reload(); 385 } 386 } 387 } 388 389 function addDrag(item) { 390 var parent = item.parentNode.parentNode; 391 parent.setAttribute('draggable', true); 392 for(var i = 0; i < dragData.length; i++) { 393 if(parent.dataset.id == dragData[i].id) { 394 dragData[i].draw = false; 395 console.log(dragData[i]); 396 } 397 } 398 } 399 400 function draw(item) { 401 var parent = item.parentNode.parentNode; 402 parent.setAttribute('draggable', true); 403 for(var i = 0; i < dragData.length; i++) { 404 if(parent.dataset.id == dragData[i].id) { 405 if(dragData[i].draw == true) { 406 $('svg').mousemove(function(e) { 407 console.log(parent.dataset.id); 408 for(var i = 0; i < dragData.length; i++) { 409 if(parent.dataset.id == dragData[i].id) { 410 console.log(dragData[i]); 411 if(dragData[i].link[dragData[i].link.length - 1]) { 412 dragData[i].link[dragData[i].link.length - 1].dx = e.offsetX; 413 dragData[i].link[dragData[i].link.length - 1].dy = e.offsetY-10; 414 dragData[i].link[dragData[i].link.length - 1].mx1 = dragData[i].outx; 415 dragData[i].link[dragData[i].link.length - 1].my1 = dragData[i].dy > dragData[i].outy ? dragData[i].outy + (dragData[i].dy - dragData[i].outy) / 3 : dragData[i].outy - (dragData[i].dy - dragData[i].outy) / 3; 416 dragData[i].link[dragData[i].link.length - 1].mx2 = dragData[i].outx + (dragData[i].dx - dragData[i].outx) / 2, 417 dragData[i].link[dragData[i].link.length - 1].my2 = dragData[i].outy + (dragData[i].dy - dragData[i].outy) / 2 418 } 419 ////////////////////////////////////////////// 420 dragData[i].dx = e.offsetX; 421 dragData[i].dy = e.offsetY-10; 422 dragData[i].mx1 = dragData[i].outx; 423 if(dragData[i].dy > dragData[i].outy) { 424 dragData[i].my1 = dragData[i].outy + (dragData[i].dy - dragData[i].outy) / 3; 425 } else { 426 dragData[i].my1 = dragData[i].outy - (dragData[i].dy - dragData[i].outy) / 3; 427 } 428 dragData[i].mx2 = dragData[i].outx + (dragData[i].dx - dragData[i].outx) / 2 429 dragData[i].my2 = dragData[i].outy + (dragData[i].dy - dragData[i].outy) / 2 430 } 431 } 432 reload(); 433 console.log(2333); 434 }) 435 } else { 436 $('svg').unbind('mousemove'); 437 } 438 439 } 440 } 441 } 442 443 function noMove() { 444 $('svg').unbind('mousemove'); 445 } 446 $('svg').mouseup(function(e) { 447 console.log(e.target); 448 $('svg').unbind('mousemove'); 449 for(var i = 0; i < dragData.length; i++) { 450 dragData[i].draw = false; 451 } 452 console.log('起来了'); 453 }) 454 </script> 455 </body> 456 457 </html>
参考了http://blog.csdn.net/zhaoxiang66/article/details/78063271
根据大神的思路加强了功能,修复了bug