<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
#d1 {
width: 800px;
height: 800px;
border: 1px solid #ccc;
position: relative;
background: #fafafa;
} #d1>div {
width: 130px;
height: 30px;
border: 1px solid #ccc;
border-radius: 8px;
position: absolute;
z-index: 2;
text-align: center;
line-height: 30px;
background: #fff;
} #d1>svg {
width: 100%;
height: 100%;
position: absolute;
z-index: 1
} .input .point {
position: absolute;
border: 6px solid transparent;
border-top: 6px solid #ccc;
top: 0px;
left: 58px;
} .input .circle {
position: absolute;
width: 10px;
height: 10px;
border: 1px solid #ccc;
top: -7px;
left: 60px;
border-radius: 50%;
background: #fff;
} .output .circle {
position: absolute;
width: 15px;
height: 15px;
border: 1px solid #ccc;
bottom: -10px;
left: 57px;
border-radius: 50%;
background: #fff;
cursor: crosshair;
z-index: 10;
} .output .circle:hover {
background: #FC9901;
}
</style>
</head> <body>
<ul class="shuiguo">
<li draggable="true" data-name="ps1">ps1</li>
<li draggable="true" data-name="ps2">ps2</li>
<li draggable="true" data-name="ps3">ps3</li>
<li draggable="true" data-name="ps4">ps4</li>
<li draggable="true" data-name="switch">switch</li>
</ul>
<div id="d1">
<svg> </svg>
</div>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript">
var dragData = [];
//重置拖拽后流程图展示
function reload(isend) {
$(function() {
var html = "";
var g = `
<defs>
<marker id="markerArrow1" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,1 L0,5 L3,3 z" fill="#CCCCCC"></path>
</marker>
<marker id="markerArrow2" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,1 L0,5 L3,3 z" fill="#cccdff"></path>
</marker>
<marker id="markerArrow3" markerWidth="10" markerHeight="10" refX="3" refY="2.6" orient="auto" markerUnits="strokeWidth">
<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"/>
</marker>
</defs>
`;
if($('svg').siblings()) { //清除$('svg')范围外的所有元素
var prev = $('svg').siblings();
for(var i = 0; i < prev.length; i++) {
prev[i].remove();
}
}
console.log(dragData);
for(var i = 0; i < dragData.length; i++) { //循环dragData,重置流程图所有dom节点
if(dragData[i] != undefined) {
var data = dragData[i];
html +=
`
<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)">
<span class = "${data.icon}" data-id = "${data.id}"></span>
<span data-id = "${data.id}">${data.label}</span>
<div class = "output">
<span class = "circle" title = "输出" onmousedown = "noDrag(this)" onmouseup = "addDrag(this)" onmouseleave = "draw(this)" onmouseenter = "noMove()" data-id = "${data.id}"></span>
</div>
</div>
`
if(data.link.length > 0) {
for(var j = 0; j < data.link.length; j++) {
g +=
`
<g id="${data.link[j].name}">
<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)"/>
</g>
`
}
}
}
}
$('svg').before(html);
$('svg').html(g);
if(isend) {
$('svg').on('mouseenter', "path", function() {
$(this).attr({
"stroke": "#cccdff",
"marker-end": "url(#markerArrow2)",
"marker-mid": "url(#markerArrow3)"
})
}).on('mouseleave', "path", function() {
$(this).attr({
"stroke": "#cccccc",
"marker-end": "url(#markerArrow1)",
"marker-mid": ""
})
}).on('click', "path", function() {
var $p = $(this).parent();
var id = $p[0].id;
for(var i = 0; i < dragData.length; i++) {
var data = dragData[i];
for(var j = 0; j < data.link.length; j++) {
if(id == data.link[j].name) {
data.link.splice(j, 1)
}
}
for(var j = 0; j < data.linked.length; j++) {
if(id == data.linked[j].name) {
data.linked.splice(j, 1)
}
}
}
$p.remove()
});
} else {
$('svg').off('mouseenter mouseleave', "path");
}
console.log($('svg').siblings());
})
}
//reload();
document.getElementById('d1').ondragover = function(e) {
e.preventDefault(); //流程图展示区阻止默认事件
}
var dWidth = Number($('#d1').css('width').slice(0, -2)); //流程图展示区域宽度
console.log(dWidth);
var dHeight = Number($('#d1').css('height').slice(0, -2)); //流程图展示区域高度
console.log(dHeight);
var dClient = $("#d1").offset().top; //流程图展示区偏移位置top
var dLeft = $("#d1").offset().left; //流程图展示区偏移位置left
console.log('顶部位置', dClient);
console.log('左边位置', dLeft); //模块拖进流程图后,初始化拖拽方法
/*
* word:模块名称
* name:模块数据名称
* type:拖拽事件类型,用于判断来执行不同拖拽事件,"outside":拖拽完成,"inside":开始拖拽
* id:模块id
*/
function drag(word, name, type, id) {
console.log(type);
console.log(name);
//在可拖动元素放置在 <div> 元素中时执行事件ondrop
document.getElementById('d1').ondrop = function(e) {
var sTop = $(document).scrollTop(); //文档滚动条偏移量top
var sLeft = $(document).scrollLeft(); //文档滚动条偏移量left
console.log('e.target', e.target.dataset.id);
var x, y;
console.log('e.clientX', e.clientX);
console.log('e.clientY', e.clientY);
if((dWidth - e.clientX + dLeft + 65) - sLeft >= 132) {
x = e.clientX - 65 - dLeft + sLeft;
} else {
x = dWidth - 133;
}
if((e.clientX - dLeft) < 65) {
x = 1;
}
if((dHeight - e.clientY + dClient + 15) - sTop >= 33) {
y = e.clientY - 15 - dClient + sTop;
} else {
y = dHeight - 33;
}
if(e.clientY - 15 - dClient + sTop < 0) {
y = 1;
}
if(type == "outside") {
console.log('放下了');
dragData.push({
id: dragData.length,
label: word,
name: name,
x: x, //模块相对展示区域的位移x
y: y, //模块相对展示区域的位移y
outx: x + 68, //模块输出点位置x/贝塞尔曲线起点x
outy: y + 30, //模块输出点位置y/贝塞尔曲线起点y
inx: x + 65, //模块输入点位置x
iny: y - 1, //模块输入点位置y
link: [], //存放由该模块连接的关联线数据数组
linked: [], //存放由其他模块连接该模块的关联线数据数组
dx: 0,
dy: 0,
mx1: 0,
my1: 0,
mx2: 0,
my2: 0,
style: name,
draw: false,
icon: name + "Icon"
});
console.log(dragData);
reload(1);
}
if(type == "inside") {
console.log(word, name, type, id);
for(var i = 0; i < dragData.length; i++) {
if(id == dragData[i].id) {
dragData[i].x = x;
dragData[i].y = y;
dragData[i].outx = dragData[i].x + 68;
dragData[i].outy = dragData[i].y + 30;
dragData[i].inx = dragData[i].x + 65;
dragData[i].iny = dragData[i].y - 1;
console.log('dragData[i].link', dragData[i].link);
for(let j = 0; j < dragData[i].link.length; j++) {
dragData[i].link[j].linkId = parseFloat(dragData[i].link[j].name.split("|")[1]);
}
for(var k = 0; k < dragData[i].linked.length; k++) {
console.log('dragData[i].linked[k]', dragData[i].linked[k]);
for(let j = 0; j < dragData.length; j++) {
if(dragData[i].linked[k].linkedNum == dragData[j].id) {
console.log('ID一样了啊');
for(let m = 0; m < dragData[j].link.length; m++) {
if(dragData[i].linked[k].name == dragData[j].link[m].name) {
console.log("名字一样了啊");
dragData[j].link[m].dx = dragData[i].inx;
dragData[j].link[m].dy = dragData[i].iny-10;
dragData[j].link[m].mx1 = dragData[j].outx;
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;
dragData[j].link[m].mx2 = dragData[j].outx + (dragData[j].link[m].dx - dragData[j].outx) / 2,
dragData[j].link[m].my2 = dragData[j].outy + (dragData[j].link[m].dy - dragData[j].outy) / 2
}
}
}
}
}
if(dragData[i].link.length > 0) {
for(var j = 0; j < dragData[i].link.length; j++) {
dragData[i].link[j].mx1 = dragData[i].outx;
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;
dragData[i].link[j].mx2 = dragData[i].outx + (dragData[i].link[j].dx - dragData[i].outx) / 2,
dragData[i].link[j].my2 = dragData[i].outy + (dragData[i].link[j].dy - dragData[i].outy) / 2
}
}
}
}
reload(1);
}
}
}
var shuiguo = $('.shuiguo li');
var isondrag = 0;
console.log(shuiguo);
for(var i = 0; i < shuiguo.length; i++) {
console.log(shuiguo[i]);
shuiguo[i].ondragstart = function() {
console.log('东完了')
drag(this.innerHTML, this.dataset.name, 'outside');
}
} function insideDrag(item) {
console.log(item);
if(item.getAttribute('draggable')) {
drag(item.dataset.label, item.className, 'inside', item.dataset.id);
}
} function noDrag(item) {
event.preventDefault();
event.stopPropagation();
console.log(item.parentNode.parentNode);
var parent = item.parentNode.parentNode;
parent.setAttribute('draggable', false);
for(var i = 0; i < dragData.length; i++) {
for(var d = 0; d < dragData[i].link.length; d++) {
if(!~dragData[i].link[d].name.indexOf("|")) {
dragData[i].link.splice(d, 1)
}
}
if(parent.dataset.id == dragData[i].id) {
dragData[i].draw = true;
dragData[i].link.push({
name: parent.dataset.id + parent.className,
dx: 0,
dy: 0,
mx1: 0,
my1: 0,
mx2: 0,
my2: 0
});
$('body').on('mouseup', function(e) {
for(var j = 0; j < dragData.length; j++) {
if(parent.dataset.id == dragData[j].id) {
console.log('页面抬起了');
dragData[j].draw = false;
var $dom = $(e.target).data("drag") ? $(e.target) : $(e.target).closest("div[data-drag]");
if($dom.length) {
if($dom.data("drag") && $dom[0].dataset.id != dragData[j].id) { //判断是否关联另外模块,非自己
$('svg').unbind('mousemove');
var name = dragData[j].link[dragData[j].link.length - 1].name + "|" + $dom[0].dataset.id + $dom[0].className;
var isontbe = 0; //判断是否存在关联
for(let i = 0; i < dragData.length; i++) {
if($dom[0].dataset.id == dragData[i].id) {
for(let c = 0; c < dragData[i].linked.length; c++) {
if(name == dragData[i].linked[c].name) {
isontbe = 1
}
}
if(!isontbe) { //不存在时候存入linked
dragData[i].linked.push({
name: name,
linkedNum: parseFloat(name)
})
}
}
}
if(!isontbe) { //不存在时候生成link数据
dragData[j].link[dragData[j].link.length - 1].name = name;
dragData[j].link[dragData[j].link.length - 1].dx = Number($dom[0].dataset.inx);
dragData[j].link[dragData[j].link.length - 1].dy = Number($dom[0].dataset.iny)-10;
} else {
dragData[j].link.splice(dragData[j].link.length - 1, 1);
}
} else {
dragData[j].link.splice(dragData[j].link.length - 1, 1);
}
} else {
dragData[j].link.splice(dragData[j].link.length - 1, 1);
}
$('svg').unbind('mousemove');
reload(1);
}
}
$('body').unbind('mouseup');
})
//reload();
}
}
} function addDrag(item) {
var parent = item.parentNode.parentNode;
parent.setAttribute('draggable', true);
for(var i = 0; i < dragData.length; i++) {
if(parent.dataset.id == dragData[i].id) {
dragData[i].draw = false;
console.log(dragData[i]);
}
}
} function draw(item) {
var parent = item.parentNode.parentNode;
parent.setAttribute('draggable', true);
for(var i = 0; i < dragData.length; i++) {
if(parent.dataset.id == dragData[i].id) {
if(dragData[i].draw == true) {
$('svg').mousemove(function(e) {
console.log(parent.dataset.id);
for(var i = 0; i < dragData.length; i++) {
if(parent.dataset.id == dragData[i].id) {
console.log(dragData[i]);
if(dragData[i].link[dragData[i].link.length - 1]) {
dragData[i].link[dragData[i].link.length - 1].dx = e.offsetX;
dragData[i].link[dragData[i].link.length - 1].dy = e.offsetY-10;
dragData[i].link[dragData[i].link.length - 1].mx1 = dragData[i].outx;
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;
dragData[i].link[dragData[i].link.length - 1].mx2 = dragData[i].outx + (dragData[i].dx - dragData[i].outx) / 2,
dragData[i].link[dragData[i].link.length - 1].my2 = dragData[i].outy + (dragData[i].dy - dragData[i].outy) / 2
}
//////////////////////////////////////////////
dragData[i].dx = e.offsetX;
dragData[i].dy = e.offsetY-10;
dragData[i].mx1 = dragData[i].outx;
if(dragData[i].dy > dragData[i].outy) {
dragData[i].my1 = dragData[i].outy + (dragData[i].dy - dragData[i].outy) / 3;
} else {
dragData[i].my1 = dragData[i].outy - (dragData[i].dy - dragData[i].outy) / 3;
}
dragData[i].mx2 = dragData[i].outx + (dragData[i].dx - dragData[i].outx) / 2
dragData[i].my2 = dragData[i].outy + (dragData[i].dy - dragData[i].outy) / 2
}
}
reload();
console.log(2333);
})
} else {
$('svg').unbind('mousemove');
} }
}
} function noMove() {
$('svg').unbind('mousemove');
}
$('svg').mouseup(function(e) {
console.log(e.target);
$('svg').unbind('mousemove');
for(var i = 0; i < dragData.length; i++) {
dragData[i].draw = false;
}
console.log('起来了');
})
</script>
</body> </html>

参考了http://blog.csdn.net/zhaoxiang66/article/details/78063271

根据大神的思路加强了功能,修复了bug

流程图(HTML5拖拽)的更多相关文章

  1. Html5拖拽复制

    拖拽是一种常见的特性,即抓取对象以后拖到另一个位置. 在 HTML5 中,拖拽是标准的一部分,任何元素都能够拖拽. Html5拖拽非常常见的一个功能,但是大部分拖拽的案例都是一个剪切的过程, 项目中需 ...

  2. html5拖拽

    html5拖拽一 <!DOCTYPE html> <html> <head lang="en"> <meta charset=" ...

  3. HTML5 拖拽复制功能的实现方法

    Internet Explorer 9FirefoxOpera 12ChromeSafari 5 v1.0代码部分 <!DOCTYPE html><html><head& ...

  4. 每天一个JavaScript实例-html5拖拽

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  5. HTML5拖拽功能中 dataTransfer对象详解

    有了HTML5,老板再也不用担心我们的上传了,再加上有拖拽上传是不是很酷.百度一下,有关HTML5拖拽上传的文章和实例不少,都缺不了一个至关重要的东东DataTransfer.但是详细介绍的不多,尤其 ...

  6. 基于html5拖拽api实现列表的拖拽排序

    基于html5拖拽api实现列表的拖拽排序 html代码: <ul ondrop="drop_handler(event);" ondragover="dragov ...

  7. html5拖拽事件 xhr2 实现文件上传 含进度条

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  8. html5拖拽总结

    拖拽(Drag 和 drop)是 HTML5 标准的组成部分.拖拽是一种常见的特性,即抓取对象以后拖到另一个位置. Internet Explorer 9.Firefox.Opera 12.Chrom ...

  9. HTML5拖拽实例

    最近应该会用到,借用一下......小妹儿,你又变懒了 拖拽相关属性 draggable属性是html5的全局属性,是html5支持拖放操作的方式之一,用来表示元素是否可以被拖放,draggable有 ...

随机推荐

  1. layui 关闭弹出层方法

    layer.closeAll();//疯狂模式,关闭所有层 layer.closeAll('dialog'); //关闭信息框 layer.closeAll('page');//关闭所有页面层 lay ...

  2. Handler Looper MessageQueue 之间的关系

    Handler Looper MessageQueue 之间的关系 handler在安卓开发中常用于更新界面ui,以及其他在主线程中的操作.内部结构大概图为: 1.handler持有一个Looper对 ...

  3. Spring全家桶之springMVC(二)

    spring mvc中url-pattern的写法 1.设置url-pattern为*.do 之前我们在web.xml文件中配置DispatcherServlet的时候,将url-pattern配置为 ...

  4. 案例 (一)如何把python项目部署到linux服务器上

      一.背景 用Python写了个脚本,需要部署到Linux环境的服务器上,由于服务器linux系统(centos,redhat等)自带的是python2,现在的python萌新都是从python3开 ...

  5. orcle报错:ORA-12737:Instant Client Light:unsupported server character set ZHS16GBK

    我们用Navacat连接Oracle数据库的时候,会提示ORA-12737:Instant Client Light:unsupported server character set ZHS16GBK ...

  6. HDU6035 Colorful Tree

    题目链接:https://vjudge.net/problem/HDU-6035 题目大意: 多样例输入. 对于每一个样例,给出 n \((2 \le n \le 200000)\) 个结点的一棵树, ...

  7. LightOJ1220

    题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1220 题目大意: 给你一个 x,请求出一个最大的 p 使得 np = x(n为 ...

  8. POJ1661

    题目链接:http://poj.org/problem?id=1661 解题思路: 离散化处理 + DP. 首先,纵坐标除了用来判断老鼠是否会摔死之外基本没用,主要考虑横坐标,只要求出在横坐标上必须走 ...

  9. Keyboard Shortcuts Reference

    Sublime Text 3快捷键 Ctrl + Shift + P 打开命令面板 Ctrl + P 搜索项目中的文件 Ctrl + G 跳到第几行 Ctrl + W 关闭当前打开文件 Ctrl + ...

  10. 测试开发专题:spring-boot如何使用JPA进行双向一对多配置

    本片文章我们主要介绍spring-boot如何进行JPA的配置以及如何进行实体间的一对多配置. 依赖准备 要在spring-boot使用jpa需要在项目中有进入相关的依赖,pom文件里加入下面内容 & ...