<!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. Postman学习宝典(一)

    前言:网上看到的比较好的Postman教程,既然已经有了,我就不重复造轮子了,直接copy过来. 资源来源于:米阳MeYoung Postman 入门1- 安装.变量.代理 简介 Postman 是一 ...

  2. MySQLdb安装记

    1 安装 python-devel 2. site.cfg 改mysql_config成实际位置 mysql_config = /mysqldata/mariadb530/bin/mysql_conf ...

  3. 感觉shopex现在的升级方式太慢了

    我是说产品的更新,484,485是一个经典的版本,那时候免费,shopex 系统市场占用率很高.但是485以后呢,只有小版本的更新,fxw ,ekd 都是改进版本吧,没用特别大幅度的更新.5年前,10 ...

  4. Bootstrap组件的使用

    五.常用组件 总结: boot中事件,关注两件事 1.事件是如何触发的.自定义属性触发,触发方式是这个属性的值 2.事件触发的目标 button绑定目标 data-target="#id&q ...

  5. Angular核心概念之五---过滤器

    Filter:过滤器,用于在view中呈现数据时显示为另一种格式:过滤器的本质是一个函数,接收原始数据转换为新的格式进行输出: function(oldVal){ ... return newVal ...

  6. NetAnalyzer笔记 之 十二 NetAnalyzer 6.0 的使用方法 -- 1.初识NetAnalyzer

    上次写NetAnalyzer使用方法是2016年的时候了,在后来NetAnalyzer经过了巨大的版本更变,但是因为个人原因,一直未对使用方法进行更新,现在NetAnalyzer最新的6.0已经发布了 ...

  7. 王玉兰201771010128《面向对象与程序设计(Java)》第十一周学习总结

    一:理论知识部分: (1)集合:集合(Collection或称为容器)是一种包含多个元素并提供对所包含元素操作方法的类,其包含的元素可以由同一类型的对象组成,也可以由不同类型的对象组成. A:集合类的 ...

  8. poj1149 经典建模

    http://wenku.baidu.com/view/0ad00abec77da26925c5b01c.html 以上内容均为转载 #include<queue> #include< ...

  9. h5+ 开发分享功能

    h5+ 开发微信.QQ分享功能 此处只做微信网页分享示例代码 方式一.JS+HTML+h5Plus 1.html代码 <div class="button" onclick= ...

  10. 【持续更新】springboot相关配置

    @Configuration public class MyWebMvcConfig implements WebMvcConfigurer { //注册了新的访问路径 @Override publi ...