1 <!DOCTYPE html> 2 <html lang="en" onselectstart='return false'> 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 background: #fafafa; 13 position: relative; 14 } 15 #d1 .drawContent{ 16 position: absolute; 17 width: 100%; 18 height: 100%; 19 } 20 #d1 .drawContent div { 21 width: 130px; 22 height: 30px; 23 border: 1px solid #ccc; 24 background: #fff; 25 border-radius: 8px; 26 position: absolute; 27 text-align: center; 28 line-height: 30px; 29 z-index: 2; 30 cursor: move; 31 } 32 33 #d1 .drawContent div span { 34 display: inline-block; 35 width: 130px; 36 height: 20px; 37 line-height: 20px; 38 cursor: move; 39 } 40 41 #d1 .drawContent div i { 42 display: inline-block; 43 width: 10px; 44 height: 10px; 45 background: #fff; 46 border-radius: 50%; 47 position: absolute; 48 top: -7px; 49 left: 46%; 50 border: 1px solid #ccc; 51 cursor: default; 52 } 53 54 #d1 .drawContent div s { 55 display: inline-block; 56 width: 10px; 57 height: 10px; 58 background: #fff; 59 border-radius: 50%; 60 position: absolute; 61 bottom: -7px; 62 left: 46%; 63 border: 1px solid #ccc; 64 cursor: crosshair; 65 } 66 67 #d1 .drawContent div u { 68 position: absolute; 69 display: inline-block; 70 border: 6px solid transparent; 71 border-top: 6px solid #ccc; 72 top: 0px; 73 left: 58px; 74 } 75 76 #d1 .drawContent div s:hover { 77 background: #F8BC06; 78 } 79 80 #d1 svg { 81 width: 100%; 82 height: 100%; 83 position: absolute; 84 z-index: 1; 85 } 86 87 #d2 { 88 width: 300px; 89 height: 2000px; 90 } 91 92 ul li { 93 cursor: default; 94 } 95 </style> 96 </head> 97 98 <body> 99 <ul id="Dragblock"> 100 <li data-name='xiangjiao'> 101 <span>香蕉</span> 102 </li> 103 <li data-name='pingguo'> 104 <span>苹果</span> 105 </li> 106 <li data-name='liulian'> 107 <span>榴莲</span> 108 </li> 109 <li data-name='xigua'> 110 <span>西瓜</span> 111 </li> 112 <li data-name='xihongshi'> 113 <span>西红柿</span> 114 </li> 115 </ul> 116 <div id='d1'> 117 <div class="drawContent"> 118 119 </div> 120 <svg></svg> 121 </div> 122 <div id='d2'></div> 123 <script type="text/x-handlebars-template" id="content"> 124 {{#each this}} 125 <div class="{{name}}" data-drag="1" data-id='{{id}}' data-inx='{{inx}}' data-iny='{{iny}}' style="top:{{y}}px;left:{{x}}px"> 126 <u style="display:{{arrow}}"></u> 127 <span class="label">{{label}}</span> 128 <s title="输出"></s> 129 </div> 130 {{/each}} 131 </script> 132 <script type="text/x-handlebars-template" id="line"> 133 {{#each this}} {{#each link}} 134 <g class="{{name}}"> 135 <path d="M{{../outx}} {{../outy}} Q{{mx1}} {{my1}} {{mx2}} {{my2}} T{{dx}} {{dy}}" stroke="#CCCCCC" fill="none" style="stroke-width: 1px;" /> 136 </g> 137 {{/each}} {{/each}} 138 </script> 139 <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script> 140 <script src="https://cdn.bootcss.com/handlebars.js/4.0.10/handlebars.min.js"></script> 141 <script type="text/javascript"> 142 var element; 143 // 获得容器的宽度 144 var dWidth = Number($('#d1').css('width').slice(0, -2)); 145 // 获得容器的高度 146 var dHeight = Number($('#d1').css('height').slice(0, -2)); 147 var dragData = [] 148 149 function reload() { 150 var myTemplate = Handlebars.compile($("#content").html()); 151 $('#d1 .drawContent').html(myTemplate(dragData)); 152 var myLine = Handlebars.compile($("#line").html()); 153 $('#d1 svg').html(myLine(dragData)); 154 } 155 // reload(); 156 //按下列表创建虚像 157 $('#Dragblock li').mousedown(function(e) { 158 var span = document.createElement('span'); 159 span.innerHTML = $(this).text(); 160 span.setAttribute('data-name', $(this).data('name')); 161 span.style.opacity = 0.6; 162 span.style.position = 'absolute'; 163 span.style.top = (e.pageY - 8) + 'px'; 164 span.style.left = (e.pageX - 8) + 'px'; 165 span.style.zIndex = 5; 166 $(this).append(span); 167 element = $(this).children('span:last-child'); 168 console.log('element', element); 169 }) 170 // 文档鼠标抬起时判断在不在容器内,创建元素 171 $(document).mouseup(function(e) { 172 console.log('e.target', e.target); 173 $('#d1').unbind('mousemove'); 174 if(element) { 175 if(e.pageY > $('#d1').offset().top && e.pageX > $('#d1').offset().left) { 176 console.log('e.offsetY', e.offsetY, 'e.offsetX', e.offsetX); 177 console.log(element); 178 var x = e.pageX - $('#d1').offset().left - e.offsetX; 179 var y = e.pageY - $('#d1').offset().top - e.offsetY; 180 //判断x 181 if((x >= 0 && x <= dWidth - 132)) { 182 x = x; 183 } else if(x < 0) { 184 x = 1; 185 } else if(x > dWidth - 132) { 186 x = dWidth - 132 187 } 188 //判断y 189 if((y >= 0 && y <= dHeight - 32)) { 190 y = y; 191 } else if(y < 0) { 192 y = 1; 193 } else if(y > dHeight - 32) { 194 y = dHeight - 32 195 } 196 dragData.push({ 197 id: dragData.length, 198 name: element.data('name'), 199 draw: false, 200 label: element.text(), 201 x: x, 202 y: y, 203 outx: x + 68, 204 outy: y + 30, 205 inx: x + 65, 206 iny: y - 1, 207 link: [], 208 linked: [], 209 dx: 0, 210 dy: 0, 211 arrow: "none" 212 }) 213 reload(); 214 element.remove(); 215 element = undefined; 216 } else { 217 element.remove(); 218 element = undefined; 219 } 220 } 221 222 }) 223 //拖动虚像在文档中进行移动 224 $(document).mousemove(function(e) { 225 //console.log('x',e.pageX,'y',e.pageY); 226 if(element) { 227 element.css({ 228 'top': (e.pageY - 8) + 'px', 229 'left': (e.pageX - 8) 230 }); 231 } 232 }) 233 //给创建的新的组件加上mousedown事件 234 var waitElement; 235 $('#d1 > .drawContent').on('mousedown', 'div', function(e) { 236 waitElement = $(this); 237 console.log(waitElement); 238 var dx = e.offsetX 239 var dy = e.offsetY 240 console.log('e.offsetX', e.offsetX) 241 console.log('e.offsetY', e.offsetY) 242 //容器的mousemove事件 243 $('#d1').on("mousemove",function(e) { 244 if(waitElement) { 245 waitElement.css({ 246 top: (e.pageY - $('#d1').offset().top - dy) + 'px', 247 left: (e.pageX - $('#d1').offset().left - dx) + 'px' 248 }); 249 console.log(waitElement.data('id')); 250 var id = waitElement.data('id') 251 var x = e.pageX - $('#d1').offset().left - dx; 252 var y = e.pageY - $('#d1').offset().top - dy; 253 //判断x 254 if((x >= 0 && x <= dWidth - 132)) { 255 x = x; 256 } else if(x < 0) { 257 x = 1; 258 } else if(x > dWidth - 132) { 259 x = dWidth - 132 260 } 261 //判断y 262 if((y >= 0 && y <= dHeight - 32)) { 263 y = y; 264 } else if(y < 0) { 265 y = 1; 266 } else if(y > dHeight - 32) { 267 y = dHeight - 32 268 } 269 for(var i = 0; i < dragData.length; i++) { 270 if(id == dragData[i].id) { 271 console.log(dragData[i]); 272 dragData[i].x = x; 273 dragData[i].outx = dragData[i].x + 68; 274 dragData[i].inx = dragData[i].x + 65; 275 dragData[i].y = y; 276 dragData[i].outy = dragData[i].y + 30; 277 dragData[i].iny = dragData[i].y - 1; 278 console.log('要开始了') 279 for(let j = 0; j < dragData[i].link.length; j++) { 280 dragData[i].link[j].linkId = parseFloat(dragData[i].link[j].name.split("|")[1]); 281 } 282 for(var k = 0; k < dragData[i].linked.length; k++) { 283 console.log('dragData[i].linked[k]', dragData[i].linked[k]); 284 for(let j = 0; j < dragData.length; j++) { 285 if(dragData[i].linked[k].linkedNum == dragData[j].id) { 286 console.log('ID一样了啊'); 287 for(let m = 0; m < dragData[j].link.length; m++) { 288 if(dragData[i].linked[k].name == dragData[j].link[m].name) { 289 console.log("名字一样了啊"); 290 dragData[j].link[m].dx = dragData[i].inx; 291 dragData[j].link[m].dy = dragData[i].iny; 292 dragData[j].link[m].mx1 = dragData[j].outx; 293 dragData[j].link[m].my1 = dragData[j].link[m].dy > dragData[j].outy ? dragData[j].outy + (dragData[j].link[m].dy - dragData[j].outy) / 4 : dragData[j].outy - (dragData[j].link[m].dy - dragData[j].outy) / 4; 294 dragData[j].link[m].mx2 = dragData[j].outx + (dragData[j].link[m].dx - dragData[j].outx) / 2, 295 dragData[j].link[m].my2 = dragData[j].outy + (dragData[j].link[m].dy - dragData[j].outy) / 2 296 } 297 } 298 } 299 } 300 } 301 reload(); 302 if(dragData[i].link.length > 0) { 303 for(var j = 0; j < dragData[i].link.length; j++) { 304 dragData[i].link[j].mx1 = dragData[i].outx; 305 dragData[i].link[j].my1 = dragData[i].link[j].dy > dragData[i].outy ? dragData[i].outy + (dragData[i].link[j].dy - dragData[i].outy) / 4 : dragData[i].outy - (dragData[i].link[j].dy - dragData[i].outy) / 4; 306 dragData[i].link[j].mx2 = dragData[i].outx + (dragData[i].link[j].dx - dragData[i].outx) / 2, 307 dragData[i].link[j].my2 = dragData[i].outy + (dragData[i].link[j].dy - dragData[i].outy) / 2 308 } 309 } 310 reload(); 311 } 312 } 313 console.log(dragData); 314 reload(); 315 } 316 }) 317 }) 318 //给创建的新的组件加上mouseup事件 319 $('#d1 > .drawContent > div').mouseup(function() { 320 waitElement = undefined; 321 console.log(waitElement); 322 }) 323 //容器的mouseup事件 324 $('#d1').mouseup(function(e) { 325 console.log('我抬起了'); 326 waitElement = undefined; 327 if(waitElement) { 328 waitElement.css({ 329 top: e.pageY - $('#d1').offset().top, 330 left: e.pageX - $('#d1').offset().left 331 }) 332 } 333 }) 334 //给组件的输出圆圈加入mouseenter事件使组件不能拖拽 335 $('#d1 > .drawContent').on('mouseenter', 'div>s', function() { 336 console.log('进入了输出'); 337 waitElement = undefined; 338 $('svg').unbind('mousemove'); 339 }) 340 //先给组件的输出源加入mousedown事件,先创建连线 341 $('#d1 > .drawContent').on('mousedown', 'div>s', function(event) { 342 event.preventDefault(); 343 event.stopPropagation(); 344 //先创建连线的数据 345 console.log($(this).parent()); 346 var parent = $(this).parent(); 347 var id = parent.data('id'); 348 console.log('idididid', id); 349 for(var i = 0; i < dragData.length; i++) { 350 if(dragData[i].id == id) { 351 dragData[i].draw = true; 352 dragData[i].link.push({ 353 name: id + parent.attr('class'), 354 dx: 0, 355 dy: 0, 356 mx1: 0, 357 my1: 0, 358 mx2: 0, 359 my2: 0 360 }); 361 console.log('dragData哈哈哈哈', dragData); 362 $('body').on('mouseup', function(e) { 363 for(var j = 0; j < dragData.length; j++) { 364 if(id == dragData[j].id) { 365 console.log('页面抬起了'); 366 dragData[j].draw = false; 367 var $dom=$(e.target).data("drag")?$(e.target):$(e.target).closest("div[data-drag]"); 368 if($dom.length){ 369 if($dom.data("drag") && $dom[0].dataset.id!=dragData[j].id){//判断是否关联另外模块,非自己 370 $('svg').unbind('mousemove'); 371 var name=dragData[j].link[dragData[j].link.length - 1].name + "|" + $dom[0].dataset.id + $dom[0].className; 372 var isontbe=0;//判断是否存在关联 373 for(let i = 0; i < dragData.length; i++){ 374 if($dom[0].dataset.id == dragData[i].id){ 375 for(let c = 0; c < dragData[i].linked.length; c++){ 376 if(name==dragData[i].linked[c].name){ 377 isontbe=1 378 } 379 } 380 if(!isontbe){//不存在时候存入linked 381 dragData[i].linked.push({ 382 name: name, 383 linkedNum:parseFloat(name) 384 }) 385 dragData[i].arrow = "inline-block"; 386 } 387 } 388 } 389 if(!isontbe){//不存在时候生成link数据 390 dragData[j].link[dragData[j].link.length - 1].name = name; 391 dragData[j].link[dragData[j].link.length - 1].dx = Number($dom[0].dataset.inx); 392 dragData[j].link[dragData[j].link.length - 1].dy = Number($dom[0].dataset.iny); 393 }else{ 394 dragData[j].link.splice(dragData[j].link.length-1,1); 395 } 396 } else { 397 dragData[j].link.splice(dragData[j].link.length - 1, 1); 398 } 399 } else { 400 dragData[j].link.splice(dragData[j].link.length - 1, 1); 401 } 402 $('svg').unbind('mousemove'); 403 reload(); 404 } 405 } 406 $('body').unbind('mouseup'); 407 }) 408 } 409 } 410 }) 411 //给输出圆圈添加mouseup事件 412 $('#d1 > .drawContent').on('mouseup', 'div>s', function() { 413 var parent = $(this).parent(); 414 for(var i = 0; i < dragData.length; i++) { 415 if(parent.data('id') == dragData[i].id) { 416 dragData[i].draw = false; 417 console.log(dragData[i]); 418 } 419 } 420 }) 421 //给组件的输出源加入mouseleave事件使组件继续能够拖拽 422 $('#d1 > .drawContent').on('mouseleave', 'div>s', function(event) { 423 event.preventDefault(); 424 event.stopPropagation(); 425 console.log('离开了了输出'); 426 console.log($(this).parent()); 427 waitElement = $(this).parent(); 428 var id = waitElement.data('id') 429 //给svg加mousemove事件 430 for(var i = 0; i < dragData.length; i++) { 431 if(id == dragData[i].id) { 432 if(dragData[i].draw == true) { 433 $('svg').mousemove(function(e) { 434 for(var i = 0; i < dragData.length; i++) { 435 if(id == dragData[i].id) { 436 console.log(dragData[i]); 437 if(dragData[i].link[dragData[i].link.length - 1]) { 438 dragData[i].link[dragData[i].link.length - 1].dx = e.offsetX; 439 dragData[i].link[dragData[i].link.length - 1].dy = e.offsetY; 440 dragData[i].link[dragData[i].link.length - 1].mx1 = dragData[i].outx; 441 dragData[i].link[dragData[i].link.length - 1].my1 = dragData[i].dy > dragData[i].outy ? dragData[i].outy + (dragData[i].dy - dragData[i].outy) / 4 : dragData[i].outy - (dragData[i].dy - dragData[i].outy) / 4; 442 dragData[i].link[dragData[i].link.length - 1].mx2 = dragData[i].outx + (dragData[i].dx - dragData[i].outx) / 2, 443 dragData[i].link[dragData[i].link.length - 1].my2 = dragData[i].outy + (dragData[i].dy - dragData[i].outy) / 2 444 } 445 // 446 dragData[i].dx = e.offsetX; 447 dragData[i].dy = e.offsetY; 448 dragData[i].mx1 = dragData[i].outx; 449 if(dragData[i].dy > dragData[i].outy) { 450 dragData[i].my1 = dragData[i].outy + (dragData[i].dy - dragData[i].outy) / 4; 451 } else { 452 dragData[i].my1 = dragData[i].outy - (dragData[i].dy - dragData[i].outy) / 4; 453 } 454 dragData[i].mx2 = dragData[i].outx + (dragData[i].dx - dragData[i].outx) / 2 455 dragData[i].my2 = dragData[i].outy + (dragData[i].dy - dragData[i].outy) / 2 456 } 457 } 458 reload(); 459 console.log(2333); 460 }) 461 } else { 462 $('svg').unbind('mousemove'); 463 } 464 465 } 466 } 467 }) 468 //给svg添加mouseup事件 469 $('svg').mouseup(function(e) { 470 console.log(e.target); 471 $('svg').unbind('mousemove'); 472 for(var i = 0; i < dragData.length; i++) { 473 dragData[i].draw = false; 474 } 475 console.log('起来了'); 476 }) 477 </script> 478 </body> 479 480 </html>
转至http://blog.csdn.net/zhaoxiang66/article/details/78341632
根据大神的思路修改了bug,加强了功能,优化了代码分量