+(function (global, $, Raphael, factory) { typeof exports == "object" && typeof module != "undefined" ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.FlowDesigner = factory()); })(this, jQuery, Raphael, function () { function Start(flow, options) { this.flow = flow; //FlowDesigner类 this.paper = flow.paper; //画布 this.options = options; this.type = "start"; this.selected = false; this.id = options.id ? options.id : ""; this.isLoad = options.isLoad ? true : false; //是否是加载的元素 this.parentElem = null; //所属父级 this.parentElemStr = options.parentElem; //加载时所属父级的名称 //this.stopmatching=false; //停止匹配线,只进入的子流程才为true,其它时候是false this.element = null; //start圆 this.bmargin = 4; //外框和元素的边距 this.elementbox = null; //start圆的外框,加厚边距 this.bbox = null; //圆的真实外框 //this.$moveDiv=null; //外框拖动虚框 this.coordinate = []; //圆元素的上下左右四条边坐标 this.centerLineCoordinate = []; //圆元素的上下左右四条边坐标,为显示中心线,小一点 this.centerMargin = 10; //向中心点向外4个方向扩展的距离 //元素 this.cx = options.cx; this.cy = options.cy; this.centerpoint = [this.cx, this.cy]; this.r = options.r; this.ccelement = null; //圆心 this.centerLineY = null; this.centerLineX = null; this.lineout = []; //所有的有关出去的线 this.text = null; //文本 this.content = {}; //start数据 this.completeState = options.completeState || 0; //0 代表否 1代表已完 2代表正当 3代表还未开始 } Start.prototype = $.extend(Start.prototype, { init: function () { var number = this.flow.createStartNodeNum(); var tempName = (new Date()).getTime(); if (!this.isLoad) { this.id = "start_" + tempName; } //圆 switch (this.completeState) { case 1://蓝色 this.element = this.paper.circle(this.cx, this.cy, this.r).attr({ "fill": "#e0e9fe", "cursor": "pointer", "stroke": "#2632aa" }); break; case 2://绿色 this.element = this.paper.circle(this.cx, this.cy, this.r).attr({ "fill": "#ebf8eb", "cursor": "pointer", "stroke": "#017501" }); break; case 3://灰色 this.element = this.paper.circle(this.cx, this.cy, this.r).attr({ "fill": "#dadada", "cursor": "pointer", "stroke": "#acacac" }); break; default: this.element = this.paper.circle(this.cx, this.cy, this.r).attr({ "fill": "#ffffff", "cursor": "pointer" }); break; } this.centerpoint = [this.cx, this.cy]; this.ccelement = this.paper.circle(this.centerpoint[0], this.centerpoint[1], 2).attr({ "fill": "#ff0000", "stroke": "ff0000" }).hide(); //圆心 //真外框 this.bbox = this.element.getBBox(); //扩大的外框 this.elementbox = this.paper.rect(this.bbox.x - this.bmargin, this.bbox.y - this.bmargin, this.bbox.width + this.bmargin * 2, this.bbox.height + this.bmargin * 2).attr({ "stroke-dasharray": "- ", "stroke": "#000000", "stroke-width": 0.5, "fill": "#ff0000", "fill-opacity": 0 }); //坐标(L,R,T,B) this.coordinate.push(this.bbox.x, this.bbox.x + this.bbox.width, this.bbox.y, this.bbox.y + this.bbox.height); //中心点向外扩展centerMargin=10,得到4条边,坐标(L,R,T,B) this.centerLineCoordinate.push(this.centerpoint[0] - this.centerMargin, this.centerpoint[0] + this.centerMargin, this.centerpoint[1] - this.centerMargin, this.centerpoint[1] + this.centerMargin); //文字 if (!this.isLoad) { this.text = this.paper.text(this.centerpoint[0], this.centerpoint[1] + this.r + 12, "开始").attr({"font-size": "12px"}).toBack(); } else { this.text = this.paper.text(this.centerpoint[0], this.centerpoint[1] + this.r + 12, this.options.text).attr({"font-size": "12px"}).toBack(); } //隐藏的中心竖线 this.centerLineY = this.paper.path("M" + this.centerpoint[0] + ",0L" + this.centerpoint[0] + "," + this.flow._DEFALUTS_.height).attr({ "stroke-width": 2, "stroke": "#c1c1c1", "stroke-dasharray": "- " }).hide(); //隐藏的中心横线 this.centerLineX = this.paper.path("M0," + this.centerpoint[1] + "L" + this.flow._DEFALUTS_.width + "," + this.centerpoint[1]).attr({ "stroke-width": 2, "stroke": "#c1c1c1", "stroke-dasharray": "- " }).hide(); //添加父元素 if (!this.isLoad) { this.addParent(); } var _that = this; if (this.completeState == 0) { //圆的外框点击 this.elementbox.click(function (e) { if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { //不在加减点状态时 //小菜单 $(".right").css({ "left": _that.cx + _that.r + 10 - _that.flow.getScrollx(), "top": _that.cy - _that.r + _that.flow._DEFALUTS_.dy - _that.flow.getScrolly() }).attr("tempid", _that.id).end().find(".sequence").attr("tempid", _that.id).show(); _that.selected = true; //选中元素 var wenbenid = $(".taskinput input").attr("wenbenid"); if (wenbenid) { _that.setText(wenbenid); } _that.text.show(); } }); //圆的外框双击 this.elementbox.dblclick(function (e) { if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { var tvalue = _that.text.attr("text"); $(".taskinput input").val(tvalue); $(".taskinput input").attr("wenbenid", _that.id); //显示文本框,15是宽度为60,取中间 $(".taskinput").css({ "left": _that.cx - _that.r - 15 - _that.flow.getScrollx(), "top": (_that.cy - 10 + _that.flow._DEFALUTS_.dy - _that.flow.getScrolly()), "width": 60 }); _that.selected = true; //文本框本身隐藏 _that.text.hide(); } }); //圆的点击元素 this.element.click(function (e) { if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { _that.elementbox.show(); $(".right").css({ "left": _that.cx + _that.r + 10 - _that.flow.getScrollx(), "top": _that.cy - _that.r + _that.flow._DEFALUTS_.dy - _that.flow.getScrolly() }).attr("tempid", _that.id).end().find(".sequence").attr("tempid", _that.id).show(); } }); //圆的外层框拖动 var weiyiX = 0; var weiyiY = 0; var dropStatus = false; var startX = 0; var startY = 0; var bpz = null; var bpzcenter = null; this.elementbox.drag(function (tx, ty, x, y, e) { //move中 if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { dropStatus = true; //限制去菜单那块 if (e.clientX < (134 + _that.flow._DEFALUTS_.dx + weiyiX)) { e.clientX = 134 + _that.flow._DEFALUTS_.dx; dropStatus = false; return; } //限制画布最右侧边界 if (e.clientX > _that.flow._DEFALUTS_.width - (_that.r + _that.bmargin) * 2 + _that.flow._DEFALUTS_.dx + weiyiX) { dropStatus = false; return; } //限制头部 if (e.clientY < (0 + _that.flow._DEFALUTS_.dy + weiyiY)) { e.clientY = 0 + _that.flow._DEFALUTS_.dy; dropStatus = false; return; } //限制画布底部边界 if (e.clientY > (0 + _that.flow._DEFALUTS_.height - (_that.r + _that.bmargin) * 2 + _that.flow._DEFALUTS_.dy + weiyiY)) { dropStatus = false; return; } this.attr({ "x": e.clientX - _that.flow._DEFALUTS_.dx - weiyiX, "y": e.clientY - _that.flow._DEFALUTS_.dy - weiyiY }); //碰撞检测 var L = e.clientX - _that.flow._DEFALUTS_.dx - weiyiX; var R = L + _that.r * 2; var T = e.clientY - _that.flow._DEFALUTS_.dy - weiyiY; var B = T + _that.r * 2; bpz = _that.flow.collision(_that, L, R, T, B); //被碰撞 if (bpz != null && bpz.type != "subProcess") { dropStatus = false; } bpzcenter = _that.flow.collisionCenterLine(_that, L, R, T, B); //中心线匹配 } }, function (x, y, e) { //move开始 weiyiX = e.clientX - _that.flow._DEFALUTS_.dx - _that.bbox.x + _that.bmargin; //offsetX,不需要减1 weiyiY = e.clientY - _that.flow._DEFALUTS_.dy - _that.bbox.y + _that.bmargin; //offsetY,不需要减32 //console.log(e.clientY , _that.flow._DEFALUTS_.dy, _that.bbox.y , _that.bmargin); startX = _that.bbox.x - _that.bmargin; startY = _that.bbox.y - _that.bmargin; }, function (e) {//move结束 if (dropStatus == true) { var elemnetboxbbox = this.getBBox(); var cx = elemnetboxbbox.cx; var cy = elemnetboxbbox.cy; //判断是否进入子流程 if (bpz && bpz.type == "subProcess") { //说明进入在子流程中 if (_that.parentElem == null || _that.parentElem.id != bpz.id) { //表示新的入到一个子流程中 if (_that.lineout.length > 0) { //如果含有线段,则必须提示,因为进入新的空间,旧的空间中的线段需要删除 $.messager.confirm('再次确认', '该开始节点进入子流程会删除原来的线段,还要继续进入吗?', function (r) { if (!r) { _that.elementbox.attr({"x": startX, "y": startY}); //不能落下的地方就返回 } else { _that.render(cx, cy, bpzcenter); //重新渲染start的圆 } }) } else { //没有线段 _that.render(cx, cy, bpzcenter); //重新渲染start的圆 } } } else if (bpz == null) { if (_that.parentElem != null) { //原来在小空间中 if (_that.lineout.length > 0) { //如果含有线段,则必须提示,因为进入新的空间,旧的空间中的线段需要删除 var L = elemnetboxbbox.x; var R = L + _that.r * 2; var T = elemnetboxbbox.y; var B = T + _that.r * 2; //判断当前是否已经出了小空间 if (!_that.comeInSubProcess2(L, R, T, B)) { $.messager.confirm('再次确认', '该开始节点原属于子流程空间,进入父空间时会删除原来的线段,还要继续进入吗?', function (r) { if (!r) { _that.elementbox.attr({"x": startX, "y": startY}); //不能落下的地方就返回 } else { _that.render(cx, cy, bpzcenter); //重新渲染start的圆 } }) } else { //没有出小空间 _that.render(cx, cy, bpzcenter); //重新渲染start的圆 } } else { //没有线段 _that.render(cx, cy, bpzcenter); //重新渲染start的圆 } } else { //原来在大空间中 _that.render(cx, cy, bpzcenter); //重新渲染start的圆 } } } else { this.attr({"x": startX, "y": startY}); //不能落下的地方就返回 } dropStatus = false; return false; }); } else if (this.completeState == 1 || this.completeState == 2) { this.element.mouseover(function (e) { $("[id*=divshow_]").hide(); var wheight = e.view.innerHeight; //屏幕大小 var wheight2 = Math.floor(wheight / 2);//屏幕大小的一半 var name = "divshow_" + _that.id; if ($("#" + name).length == 0) { //创建 if (e.pageY <= wheight2) { var str = "

" + _that.getText() + "

"; } else { var str = "

" + _that.getText() + "

"; } if (_that.completeState == 1) { str += "

已办理

"; if (_that.content.activityUsers && _that.content.activityUsers.length > 0) { $.each(_that.content.activityUsers, function (i, el) { str += "

办理人员" + el.name + "办理时间" + el.time + "

办理意见" + el.advice + "

"; }) } } else if (_that.completeState == 2) { if (_that.content.waitActivityUsers && _that.content.waitActivityUsers.length > 0) { str += "

正在办理

"; $.each(_that.content.waitActivityUsers, function (i, el) { str += "

办理人员" + el.name + "开始时间" + el.time + "

"; }) } if (_that.content.activityUsers && _that.content.activityUsers.length > 0) { str += "

已办理

"; $.each(_that.content.activityUsers, function (i, el) { str += "

办理人员" + el.name + "办理时间" + el.time + "

办理意见" + el.advice + "

"; }) } } str += "
"; $("#" + _that.flow._DEFALUTS_.id).append(str); } else { if (e.pageY <= wheight2) { $("#" + name).css({"left": (e.pageX + 0), "top": (e.pageY + 0), "bottom": "auto"}).show(); $("#" + name).find(".con").css({"maxHeight": wheight2}); } else { $("#" + name).css({ "left": (e.pageX + 0), "bottom": (wheight - e.pageY + 0), "top": "auto" }).show(); $("#" + name).find(".con").css({"maxHeight": wheight2}); } } }) } }, render: function (cx, cy, bpzcenter) { //start元素重新渲染 if (bpzcenter != null) { //碰撞吸附 if (bpzcenter[0] != null && bpzcenter[1] == null) { //y轴吸附,x轴不吸附 if (bpzcenter[0].type == "start" || bpzcenter[0].type == "end" || bpzcenter[0].type == "gateway") { cx = bpzcenter[0].cx; } else if (bpzcenter[0].type == "userTask" || bpzcenter[0].type == "subProcess") { cx = bpzcenter[0].x + bpzcenter[0].w / 2; } } else if (bpzcenter[0] == null && bpzcenter[1] != null) { //x轴吸附,y轴不吸附 if (bpzcenter[1].type == "start" || bpzcenter[1].type == "end" || bpzcenter[1].type == "gateway") { cy = bpzcenter[1].cy; } else if (bpzcenter[1].type == "userTask" || bpzcenter[1].type == "subProcess") { cy = bpzcenter[1].y + bpzcenter[1].h / 2; } } else if (bpzcenter[0] != null && bpzcenter[1] != null) { //y轴吸附,x轴吸附 if (bpzcenter[0].type == "start" || bpzcenter[0].type == "end" || bpzcenter[0].type == "gateway") { cx = bpzcenter[0].cx; } else if (bpzcenter[0].type == "userTask" || bpzcenter[0].type == "subProcess") { cx = bpzcenter[0].x + bpzcenter[0].w / 2; } if (bpzcenter[1].type == "start" || bpzcenter[1].type == "end" || bpzcenter[1].type == "gateway") { cy = bpzcenter[1].cy; } else if (bpzcenter[1].type == "userTask" || bpzcenter[1].type == "subProcess") { cy = bpzcenter[1].y + bpzcenter[1].h / 2; } } } this.cx = cx; this.cy = cy; this.element.attr({"cx": cx, "cy": cy}); this.bbox = this.element.getBBox(); this.centerpoint = [cx, cy]; //圆心 this.ccelement.attr({"cx": this.centerpoint[0], "cy": this.centerpoint[1]}); //扩大的外框 this.elementbox.attr({"x": this.bbox.x - this.bmargin, "y": this.bbox.y - this.bmargin}); //修改坐标(L,R,T,B) this.coordinate[0] = this.bbox.x; this.coordinate[1] = this.bbox.x + this.bbox.width; this.coordinate[2] = this.bbox.y; this.coordinate[3] = this.bbox.y + this.bbox.height; //中心点向外扩展centerMargin=10,得到4条边,坐标(L,R,T,B) this.centerLineCoordinate = []; this.centerLineCoordinate.push(this.centerpoint[0] - this.centerMargin, this.centerpoint[0] + this.centerMargin, this.centerpoint[1] - this.centerMargin, this.centerpoint[1] + this.centerMargin); //文字 this.text.attr({"x": this.centerpoint[0], "y": this.centerpoint[1] + this.r + 12}); //移动隐藏的中心竖线 this.centerLineY.attr("path", "M" + this.centerpoint[0] + ",0L" + this.centerpoint[0] + "," + this.flow._DEFALUTS_.height); //移动隐藏的中心横线 this.centerLineX.attr("path", "M0," + this.centerpoint[1] + "L" + this.flow._DEFALUTS_.width + "," + this.centerpoint[1]); //所有出去的点,因为坐标变了,需要重绘 var _that = this; $.each(this.lineout, function (index, lineElem) { lineElem.redrawStart(_that.cx, _that.cy); }); //父元素处理 var parent = this.comeInSubProcess(); if (parent != null) { //目前进入到子流程中 parent.elementbox.attr({"stroke": "#000000", "stroke-width": 0.5}); } //无论是否有父元素,都需要进入这个方法 this.addParent(parent); }, unSelect: function () {//非选中状态 //小菜单回归原位 $(".right").css({"left": -100, "top": -100}); //外框隐藏 this.elementbox.attr({"stroke": "#000000", "stroke-width": 0.5}).hide(); //文本框 if (this.selected == true) { var wenbenid = $(".taskinput input").attr("wenbenid"); if (wenbenid) { this.setText(wenbenid); } this.text.show(); } //文本框回归原位 $(".taskinput").css({"left": -100, "top": -100}); //中心线隐藏 this.centerLineX.hide(); this.centerLineY.hide(); this.selected = false; this.ccelement.hide(); //完成情况的显示 if (this.completeState != 0) { var name = "divshow_" + this.id; $("#" + name).hide(); } }, setText: function (wenbenid) { //得到文本框的值,重新赋值给text //Raphaël\nkicks\nbutt! var tvalue = $(".taskinput input").val(); var temp = tvalue; if ($.trim(tvalue) != "" && wenbenid == this.id) { this.text.attr({"text": temp}); $(".taskinput input").val("");//清空 } }, removeElement: function () {//删除元素 this.element.remove(); this.centerLineX.remove(); this.centerLineY.remove(); this.elementbox.remove(); this.ccelement.remove(); this.text.remove(); //文本框回归 $(".taskinput").css({"left": -100, "top": -100}); //小菜单回归原位 $(".right").css({"left": -100, "top": -100}); //父元素 if (this.parentElem) { this.parentElem.removeSubElement(this); this.parentElem = null; } //移除相关的线 var templines = []; $.each(this.lineout, function (index, line) { templines.push(line); }); $.each(templines, function (index, line) { line && line.removeElement(); }); }, removeOutLine: function (line) { var _that = this; $.each(this.lineout, function (index, elem) { if (elem && elem.id == line.id) { _that.lineout.splice(index, 1); } }) }, comeInSubProcess: function () { //判断是否在子流程里面 var parent = this.flow.collisionSubProcess(this.coordinate[0], this.coordinate[1], this.coordinate[2], this.coordinate[3]); //被碰撞 return parent; }, comeInSubProcess2: function (L, R, T, B) {//判断是否在子流程里面 var parent = this.flow.collisionSubProcess(L, R, T, B); //被碰撞 return parent; }, addParent: function (parent) {//在子流程里的处理 //判断落点是否在子流程内,如果落在子流程内,则需要修改parentElem if (!parent) { parent = this.flow.collisionSubProcess(this.coordinate[0], this.coordinate[1], this.coordinate[2], this.coordinate[3]); //被碰撞 } if (parent != null) { var ids = []; $.each(parent.subElement, function (index, elem) { ids.push(elem.id); }) if ($.inArray(this.id, ids) == -1) { this.parentElem = parent; parent.subElement.push(this); //表示新加入的到某个节点上,则原来的所有的线段需要移除 //移除相关的线 this.removeLine(); //节点置前 //this.element.toFront(); this.elementbox.toFront(); } } else {//没有父元素 if (this.parentElem) { this.parentElem.removeSubElement(this); this.parentElem = null; //表示新加入的到其他的,则原来子流程中的所有的线段需要移除 this.removeLine(); } } }, getText: function () { return this.text.attr("text"); }, removeLine: function () { //删除线段 var tempoutlines = []; $.each(this.lineout, function (index, line) { if (!line.self) { tempoutlines.push(line); } }); $.each(tempoutlines, function (index, line) { line && line.removeElement(); if (line) { delete this.flow.alllines[line.id]; //删除线元素 } }); } }); //任务节点 function UserTask(flow, options) { this.flow = flow; //FlowDesigner类的实例 this.paper = flow.paper; //画布rapheal this.options = options; this.type = "userTask"; this.selected = false; this.id = options.id ? options.id : ""; this.isLoad = options.isLoad ? true : false; //是否是加载的元素 this.parentElem = null; //所属父级 this.parentElemStr = options.parentElem; //加载时所属父级的名称 this.element = null; //任务方块 this.elementbox = null; //扩大外框 this.bbox = null; //外框 this.coordinate = []; //当前元素的上下左右四条边坐标 this.fourpoint = []; //四个元素顶点坐标 this.centerLineCoordinate = []; //圆元素的上下左右四条边坐标,为显示中心线,小一点 this.centerMargin = 10; //向中心点向外4个方向扩展的距离 //控制点 //this.$elementctrl1 = null; //this.$elementctrl4 = null; //元素 this.x = options.x; //顶点坐标x this.y = options.y;//顶点坐标y this.w = options.w;//宽 this.h = options.h;//高 this.angle = 4; //弧度 this.bmargin = 4; //外框和元素的边距 this.text = null; //文本 this.ccelement = null; //圆心 this.centerpoint = []; //矩形的中心点 this.linein = []; //所有进来的线 this.lineout = [];//所有出去的线 this.content = {}; //任务节点的数据 this.completeState = options.completeState || 0; //0 代表否 1代表已完 2代表正当 3代表还未开始 } UserTask.prototype = $.extend(UserTask.prototype, { init: function () { var number = this.flow.createTaskNum(); var tempName = (new Date()).getTime(); if (!this.isLoad) { this.id = "userTask_" + tempName; } //矩形框 switch (this.completeState) { case 1://蓝色 this.element = this.paper.rect(this.x, this.y, this.w, this.h, this.angle).attr({ "fill": "#e0e9fe", "cursor": "pointer", "stroke": "#2632aa" }).toFront(); break; case 2://绿色 this.element = this.paper.rect(this.x, this.y, this.w, this.h, this.angle).attr({ "fill": "#ebf8eb", "cursor": "pointer", "stroke": "#017501" }).toFront(); break; case 3://灰色 this.element = this.paper.rect(this.x, this.y, this.w, this.h, this.angle).attr({ "fill": "#dadada", "cursor": "pointer", "stroke": "#acacac" }).toFront(); break; default: this.element = this.paper.rect(this.x, this.y, this.w, this.h, this.angle).attr({ "fill": "#f9f9f9", "cursor": "pointer" }).toFront(); break; } //外框 this.bbox = this.element.getBBox(); //扩大外框 this.elementbox = this.paper.rect(this.bbox.x - this.bmargin, this.bbox.y - this.bmargin, this.bbox.width + this.bmargin * 2, this.bbox.height + this.bmargin * 2).attr({ "stroke-dasharray": "- ", stroke: "#000000", "stroke-width": 0.5, "fill": "#ff0000", "fill-opacity": 0 }); //坐标(L,R,T,B) this.coordinate.push(this.bbox.x, this.bbox.x + this.bbox.width, this.bbox.y, this.bbox.y + this.bbox.height); //文字 if (!this.isLoad) { this.text = this.paper.text(this.bbox.x + this.bbox.width / 2, this.bbox.y + this.bbox.height / 2, "任务" + number).attr({"font-size": "14px"}); } else { this.text = this.paper.text(this.bbox.x + this.bbox.width / 2, this.bbox.y + this.bbox.height / 2, this.options.text).attr({"font-size": "14px"}); } //中心点坐标 this.centerpoint = [this.bbox.x + this.bbox.width / 2, this.bbox.y + this.bbox.height / 2]; //根据中心点和宽度高度得到四个顶点 //定点开始顺时针 this.fourpoint = [{"x": this.x, "y": this.y}, {"x": this.x + this.w, "y": this.y}, { "x": this.x + this.w, "y": this.y + this.h }, {"x": this.x, "y": this.y + this.h}]; //中心点向外扩展centerMargin=10,得到4条边,坐标(L,R,T,B) this.centerLineCoordinate.push(this.centerpoint[0] - this.centerMargin, this.centerpoint[0] + this.centerMargin, this.centerpoint[1] - this.centerMargin, this.centerpoint[1] + this.centerMargin); //隐藏的中心竖线 this.centerLineY = this.paper.path("M" + this.centerpoint[0] + ",0L" + this.centerpoint[0] + "," + this.flow._DEFALUTS_.height).attr({ "stroke-width": 2, "stroke": "#c1c1c1", "stroke-dasharray": "- " }).hide(); //隐藏的中心横线 this.centerLineX = this.paper.path("M0," + this.centerpoint[1] + "L" + this.flow._DEFALUTS_.width + "," + this.centerpoint[1]).attr({ "stroke-width": 2, "stroke": "#c1c1c1", "stroke-dasharray": "- " }).hide(); this.ccelement = this.paper.circle(this.centerpoint[0], this.centerpoint[1], 2).attr({ "fill": "#ff0000", "stroke": "ff0000" }).hide(); //圆心 if (!this.isLoad) { //添加父元素 this.addParent(); } var _that = this; if (this.completeState == 0) { //方块的外框点击 this.elementbox.click(function (e) { if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { //小菜单 $(".right").css({ "left": _that.x + _that.w + 10 - _that.flow.getScrollx(), "top": _that.y + _that.flow._DEFALUTS_.dy - _that.flow.getScrolly() }).attr("tempid", _that.id).end().find(".sequence").attr("tempid", _that.id).show(); //_that.$elementctrl1.hide(); //_that.$elementctrl4.hide(); _that.selected = true; //选中元素 _that.elementbox.show(); var wenbenid = $(".taskinput input").attr("wenbenid"); if (wenbenid) { _that.setText(wenbenid); } _that.text.show(); } }); //方块的外框双击 this.elementbox.dblclick(function (e) { if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { var tvalue = _that.text.attr("text"); $(".taskinput input").val(tvalue); $(".taskinput input").attr("wenbenid", _that.id); //显示文本框 $(".taskinput").css({ "left": _that.x - _that.flow.getScrollx(), "top": (_that.y + _that.h / 2 - 10 + _that.flow._DEFALUTS_.dy - _that.flow.getScrolly()), "width": _that.w - 2 }); _that.selected = true; //文本框本身隐藏 _that.text.hide(); } }); //方块的单击 this.element.click(function (e) { if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { _that.elementbox.show(); $(".right").css({ "left": _that.x + _that.w + 10 - _that.flow.getScrollx(), "top": _that.y + _that.flow._DEFALUTS_.dy - _that.flow.getScrolly() }).attr("tempid", _that.id).end().find(".sequence").attr("tempid", _that.id).show(); //显示控制点 //_that.$elementctrl1.show(); //_that.$elementctrl4.show(); } }); //方块任务节点的外层框拖动 var weiyiX = 0; var weiyiY = 0; var dropStatus = false; var startX = 0; var startY = 0; var bpz = null; var bpzcenter = null; var startpointx = 0; var startpointy = 0; this.elementbox.drag(function (tx, ty, x, y, e) { //move中 if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { dropStatus = true; //限制去菜单那块 if (e.clientX < (134 + _that.flow._DEFALUTS_.dx + weiyiX)) { e.clientX = 134 + _that.flow._DEFALUTS_.dx; dropStatus = false; return; } //限制画布最右侧边界 if (e.clientX > _that.flow._DEFALUTS_.width - (_that.w + _that.bmargin * 2) + _that.flow._DEFALUTS_.dx + weiyiX) { dropStatus = false; return; } //限制头部 if (e.clientY < (0 + _that.flow._DEFALUTS_.dy + weiyiY)) { e.clientY = 0 + _that.flow._DEFALUTS_.dy; dropStatus = false; return; } //限制画布底部边界 if (e.clientY > (0 + _that.flow._DEFALUTS_.height - (_that.h + _that.bmargin * 2) + _that.flow._DEFALUTS_.dy + weiyiY)) { dropStatus = false; return; } this.attr({ "x": e.clientX - _that.flow._DEFALUTS_.dx - weiyiX, "y": e.clientY - _that.flow._DEFALUTS_.dy - weiyiY }); //碰撞检测 var L = e.clientX - _that.flow._DEFALUTS_.dx - weiyiX; var R = L + _that.w; var T = e.clientY - _that.flow._DEFALUTS_.dy - weiyiY; var B = T + _that.h; bpz = _that.flow.collision(_that, L, R, T, B); //被碰撞 if (bpz != null && bpz.type != "subProcess") {//1.当碰到元素并且元素不是子流程 不可落下 dropStatus = false; } bpzcenter = _that.flow.collisionCenterLine(_that, L, R, T, B); //中心线匹配 } }, function (x, y, e) { //move开始 //文本框回归原位 $(".taskinput").css({"left": -100, "top": -100}); weiyiX = e.clientX - _that.flow._DEFALUTS_.dx - _that.bbox.x + _that.bmargin; //offsetX,不需要减1 weiyiY = e.clientY - _that.flow._DEFALUTS_.dy - _that.bbox.y + _that.bmargin; //offsetY,不需要减32 startX = _that.bbox.x - _that.bmargin; startY = _that.bbox.y - _that.bmargin; startpointx = e.clientX; startpointy = e.clientY; }, function (e) {//move结束 var endpointx = e.clientX; var endpointy = e.clientY; if (Math.abs(endpointx - startpointx) < 2 && Math.abs(endpointy - startpointy) < 2) {//阻止点击就移动 dropStatus = false; } if (dropStatus == true) { var x = e.clientX - _that.flow._DEFALUTS_.dx - weiyiX; var y = e.clientY - _that.flow._DEFALUTS_.dy - weiyiY; //判断是否进入子流程 if (bpz && bpz.type == "subProcess") { //说明进入在子流程中 if (_that.parentElem == null || _that.parentElem.id != bpz.id) { //表示新的入到一个子流程中 if (_that.linein.length > 0 || _that.lineout.length > 0) { //如果含有线段,则必须提示,因为进入新的空间,旧的空间中的线段需要删除 $.messager.confirm('再次确认', '该任务节点进入子流程会删除原来的线段,还要继续进入吗?', function (r) { if (!r) { _that.elementbox.attr({"x": startX, "y": startY}); //不能落下的地方就返回 } else { _that.render(x, y, bpzcenter); } }) } else { //没有线段 _that.render(x, y, bpzcenter); } } } else if (bpz == null) { if (_that.parentElem != null) { //原来在小空间中 if (_that.linein.length > 0 || _that.lineout.length > 0) { //如果含有线段,则必须提示,因为进入新的空间,旧的空间中的线段需要删除 var L = x; var R = L + _that.w; var T = y; var B = T + _that.h; //判断当前是否已经出了小空间 if (!_that.comeInSubProcess2(L, R, T, B)) { $.messager.confirm('再次确认', '该任务节点原属于子流程空间,进入父空间时会删除原来的线段,还要继续进入吗?', function (r) { if (!r) { _that.elementbox.attr({"x": startX, "y": startY}); //不能落下的地方就返回 } else { _that.render(x, y, bpzcenter); } }) } else { //没有出小空间 _that.render(x, y, bpzcenter); } } else { //没有线段 _that.render(x, y, bpzcenter); } } else { //原来在大空间中 _that.render(x, y, bpzcenter); } } } else { _that.elementbox.attr({"x": startX, "y": startY}); //不能落下的地方就返回 } dropStatus = false; return false; }); } else if (this.completeState == 1 || this.completeState == 2) { this.element.mouseover(function (e) { $("[id*=divshow_]").hide(); var wheight = e.view.innerHeight; //屏幕大小 var wheight2 = Math.floor(wheight / 2);//屏幕大小的一半 var name = "divshow_" + _that.id; if ($("#" + name).length == 0) { //创建 if (e.pageY <= wheight2) { var str = "

" + _that.getText() + "

"; } else { var str = "

" + _that.getText() + "

"; } if (_that.completeState == 1) { str += "

已办理

"; if (_that.content.activityUsers && _that.content.activityUsers.length > 0) { $.each(_that.content.activityUsers, function (i, el) { str += "

办理人员" + el.name + "办理时间" + el.time + "

办理意见" + el.advice + "

"; }) } } else if (_that.completeState == 2) { if (_that.content.waitActivityUsers && _that.content.waitActivityUsers.length > 0) { str += "

正在办理

"; $.each(_that.content.waitActivityUsers, function (i, el) { str += "

办理人员" + el.name + "开始时间" + el.time + "

"; }) } if (_that.content.activityUsers && _that.content.activityUsers.length > 0) { str += "

已办理

"; $.each(_that.content.activityUsers, function (i, el) { str += "

办理人员" + el.name + "办理时间" + el.time + "

办理意见" + el.advice + "

"; }) } } str += "
"; $("#" + _that.flow._DEFALUTS_.id).append(str); } else { if (e.pageY <= wheight2) { $("#" + name).css({"left": (e.pageX + 0), "top": (e.pageY + 0), "bottom": "auto"}).show(); $("#" + name).find(".con").css({"maxHeight": wheight2}); } else { $("#" + name).css({ "left": (e.pageX + 0), "bottom": (wheight - e.pageY + 0), "top": "auto" }).show(); $("#" + name).find(".con").css({"maxHeight": wheight2}); } } }) } /* 控制点4的移动 //控制点4的移动 var ctrl4startx = 0; var ctrl4starty = 0; var ctrl4oldstartx = 0; var ctrl4oldstarty = 0; this.$elementctrl4.draggable({ cursor: "se-resize", revert: true, onStartDrag: function (e) { if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { ctrl4oldstartx = ctrl4startx = e.clientX; ctrl4oldstarty = ctrl4starty = e.clientY; } }, onDrag: function (e) { if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { var elementboxbox = _that.elementbox.getBBox(); var width = elementboxbox.width; var height = elementboxbox.height; var ctrl4dragpointx = e.clientX; var ctrl4dragpointy = e.clientY; width = width + ctrl4dragpointx - ctrl4startx; height = height + ctrl4dragpointy - ctrl4starty; _that.elementbox.attr({ "width": width, "height": height }); ctrl4startx = ctrl4dragpointx; ctrl4starty = ctrl4dragpointy; } }, onStopDrag: function (e) { if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { var ctrl4endx = e.clientX; var ctrl4endy = e.clientY; var dwidth = ctrl4endx - ctrl4oldstartx; var dheight = ctrl4endy - ctrl4oldstarty; var elementWidth = _that.element.attr("width"); var elementHeight = _that.element.attr("height"); _that.element.attr({ "width": elementWidth + dwidth, "height": elementHeight + dheight }); _that.w = elementWidth + dwidth; _that.h = elementHeight + dheight; _that.render(_that.bbox.x,_that.bbox.y,null); } } }) */ /* 控制点1的移动(移动的是left,top,width,height) // //控制点1的移动(移动的是left,top,width,height) // var ctrl1startx = 0; // var ctrl1starty = 0; // var ctrl1oldstartx = 0; // var ctrl1oldstarty = 0; // var ctr1tx = 0; // var ctr1ty = 0; // this.$elementctrl1.draggable({ // cursor: "nw-resize", // revert: true, // onStartDrag: function (e) { // ctrl1oldstartx = ctrl1startx = e.clientX; // ctrl1oldstarty = ctrl1starty = e.clientY; // var oldleft = $(this).css("left"); // var oldtop = $(this).css("top"); // ctr1tx = e.clientX - parseFloat(oldleft); // ctr1ty = e.clientY - parseFloat(oldtop); // }, // onDrag: function (e) { // var elementboxbox = _that.elementbox.getBBox(); // var width = elementboxbox.width; // var height = elementboxbox.height; // var ctrl1dragpointx = e.clientX; // var ctrl1dragpointy = e.clientY; // width = width - (ctrl1dragpointx - ctrl1startx); // height = height - (ctrl1dragpointy - ctrl1starty); // var ctr1left = e.clientX - ctr1tx - _that.flow._DEFALUTS_.dx + 10; // var ctr1top = e.clientY - ctr1ty - _that.flow._DEFALUTS_.dy + 10; // _that.elementbox.attr({ "x": ctr1left, "y": ctr1top, "width": width, "height": height }); // ctrl1startx = ctrl1dragpointx; // ctrl1starty = ctrl1dragpointy; // }, // onStopDrag: function (e) { // var ctrl1endx = e.clientX; // var ctrl1endy = e.clientY; // var x = ctrl1endx - ctr1tx - _that.flow._DEFALUTS_.dx + _that.bmargin + 10; // var y = ctrl1endy - ctr1ty - _that.flow._DEFALUTS_.dy + _that.bmargin + 10; // var dwidth = -(ctrl1endx - ctrl1oldstartx); // var dheight = -(ctrl1endy - ctrl1oldstarty); // var elementWidth = _that.element.attr("width"); // var elementHeight = _that.element.attr("height"); // //元素 // _that.element.attr({ "x": x, "y": y, "width": elementWidth + dwidth, "height": elementHeight + dheight }); // //属性 // _that.x = x; // _that.y = y; // _that.w = elementWidth + dwidth; // _that.h = elementHeight + dheight; // _that.render(x,y,null); // } // }) */ }, render: function (x, y, bpzcenter) { //userTask的渲染 if (bpzcenter != null) { if (bpzcenter[0] != null && bpzcenter[1] == null) { //y轴吸附,x轴不吸附 if (bpzcenter[0].type == "start" || bpzcenter[0].type == "end" || bpzcenter[0].type == "gateway") { x = bpzcenter[0].cx - this.w / 2; } else if (bpzcenter[0].type == "userTask" || bpzcenter[0].type == "subProcess") { x = bpzcenter[0].x + bpzcenter[0].w / 2 - this.w / 2; //因为2个元素的大小不一定相同,先到中心点,再减去自身的一半 } } else if (bpzcenter[0] == null && bpzcenter[1] != null) { //x轴吸附,y轴不吸附 if (bpzcenter[1].type == "start" || bpzcenter[1].type == "end" || bpzcenter[1].type == "gateway") { y = bpzcenter[1].cy - this.h / 2; } else if (bpzcenter[1].type == "userTask" || bpzcenter[1].type == "subProcess") { y = bpzcenter[1].y + bpzcenter[1].h / 2 - this.h / 2; //因为2个元素的大小不一定相同,先到中心点,再减去自身的一半 } } else if (bpzcenter[0] != null && bpzcenter[1] != null) { //y轴吸附,x轴吸附 if (bpzcenter[0].type == "start" || bpzcenter[0].type == "end" || bpzcenter[0].type == "gateway") { x = bpzcenter[0].cx - this.w / 2; } else if (bpzcenter[0].type == "userTask" || bpzcenter[0].type == "subProcess") { x = bpzcenter[0].x + bpzcenter[0].w / 2 - this.w / 2; //因为2个元素的大小不一定相同,先到中心点,再减去自身的一半 } if (bpzcenter[1].type == "start" || bpzcenter[1].type == "end" || bpzcenter[1].type == "gateway") { y = bpzcenter[1].cy - this.h / 2; } else if (bpzcenter[1].type == "userTask" || bpzcenter[1].type == "subProcess") { y = bpzcenter[1].y + bpzcenter[1].h / 2 - this.h / 2; //因为2个元素的大小不一定相同,先到中心点,再减去自身的一半 } } } this.x = x; this.y = y; this.element.attr({"x": x, "y": y}); this.bbox = this.element.getBBox(); this.text.attr({"x": this.bbox.x + this.bbox.width / 2, "y": this.bbox.y + this.bbox.height / 2}) //扩大的外框 this.elementbox.attr({"x": this.bbox.x - this.bmargin, "y": this.bbox.y - this.bmargin}); //修改坐标(L,R,T,B) this.coordinate[0] = this.bbox.x; this.coordinate[1] = this.bbox.x + this.bbox.width; this.coordinate[2] = this.bbox.y; this.coordinate[3] = this.bbox.y + this.bbox.height; this.centerpoint = [this.bbox.x + this.w / 2, this.bbox.y + this.h / 2]; //圆心 this.ccelement.attr({"cx": this.centerpoint[0], "cy": this.centerpoint[1]}); //根据中心点和宽度高度得到四个顶点 //定点开始顺时针 this.fourpoint = [{"x": this.x, "y": this.y}, {"x": this.x + this.w, "y": this.y}, { "x": this.x + this.w, "y": this.y + this.h }, {"x": this.x, "y": this.y + this.h}]; //中心点向外扩展centerMargin=10,得到4条边,坐标(L,R,T,B) this.centerLineCoordinate = []; this.centerLineCoordinate.push(this.centerpoint[0] - this.centerMargin, this.centerpoint[0] + this.centerMargin, this.centerpoint[1] - this.centerMargin, this.centerpoint[1] + this.centerMargin); //移动隐藏的中心竖线 this.centerLineY.attr("path", "M" + this.centerpoint[0] + ",0L" + this.centerpoint[0] + "," + this.flow._DEFALUTS_.height); //移动隐藏的中心横线 this.centerLineX.attr("path", "M0," + this.centerpoint[1] + "L" + this.flow._DEFALUTS_.width + "," + this.centerpoint[1]); //控制点 //this.$elementctrl1.css({ "left": (this.bbox.x - this.bmargin - 10), "top": (this.bbox.y - this.bmargin - 10) }); //this.$elementctrl4.css({ "left": (this.bbox.x - this.bmargin + this.bbox.width + 8), "top": (this.bbox.y - this.bmargin + this.bbox.height + 8) }); // //是否有父元素 // var parent = this.addParent(); // if (parent != null) { // //目前进入到子流程中 // parent.elementbox.attr({ "stroke": "#000000", "stroke-width": 0.5 }); // } else { // //在子流程外 // if (this.parentElem) { // this.parentElem.removeSubElement(this); // this.parentElem = null; // //表示新加入的到某个,则原来子流程中的所有的线段需要移除 // this.removeLine(); // } // } //父元素处理 var parent = this.comeInSubProcess(); if (parent != null) { //目前进入到子流程中 parent.elementbox.attr({"stroke": "#000000", "stroke-width": 0.5}); } //无论是否有父元素,都需要进入这个方法 this.addParent(parent); var _that = this; //所有出去的点,因为坐标变了,需要重绘 $.each(this.lineout, function (index, lineElem) { if (!lineElem.self) { //不是指向自身的点除外 lineElem.redrawStart(_that.bbox.cx, _that.bbox.cy); } else { //是指向自身的线,需要和节点一起变化,重绘 lineElem.renderMoveSelf(); } }); //所有进入的点,因为坐标变了,需要重绘 $.each(this.linein, function (index, lineElem) { //得到点 if (!lineElem.self) { lineElem.redrawEnd(_that.bbox.cx, _that.bbox.cy); } }); }, unSelect: function () {//非选中状态 //小菜单回归原位 $(".right").css({"left": -100, "top": -100}); if (this.selected == true) { var wenbenid = $(".taskinput input").attr("wenbenid"); if (wenbenid) { this.setText(wenbenid); } this.text.show(); } //文本框回归原位 $(".taskinput").css({"left": -100, "top": -100}); //圆心 this.ccelement.hide(); //外框隐藏 this.elementbox.attr({"stroke": "#000000", "stroke-width": 0.5}).hide(); //中心线隐藏 this.centerLineX.hide(); this.centerLineY.hide(); //this.$elementctrl1.hide(); //this.$elementctrl4.hide(); this.selected = false; //完成情况的显示 if (this.completeState != 0) { var name = "divshow_" + this.id; $("#" + name).hide(); } }, setText: function (wenbenid) { //得到文本框的值,重新赋值给text //Raphaël\nkicks\nbutt! var tvalue = $(".taskinput input").val(); var temp = tvalue; if ($.trim(tvalue) != "" && wenbenid == this.id) { var zishu = Math.floor(this.w / 14); //一行可显示的中文字数 var hangshu = parseInt(tvalue.length / zishu) + 1; //行数 var arr = []; if (tvalue.length > zishu) { for (var j = 0; j < hangshu; j++) { for (var i = j * zishu; i < (j + 1) * zishu; i = i + 1) { if (tvalue[i]) { if (arr[j]) { arr[j] += tvalue[i]; } else { arr[j] = tvalue[i]; } } } } temp = arr.join('\n'); } this.text.attr({"text": temp}); $(".taskinput input").val("");//清空 } }, removeElement: function () { this.element.remove(); this.centerLineX.remove(); this.centerLineY.remove(); this.elementbox.remove(); //this.$elementctrl1.remove(); //this.$elementctrl4.remove(); this.text.remove(); this.ccelement.remove(); //小菜单回归原位 $(".right").css({"left": -100, "top": -100}); //文本框回归 $(".taskinput").css({"left": -100, "top": -100}); //父元素 if (this.parentElem) { this.parentElem.removeSubElement(this); this.parentElem = null; } //移除相关的线 var tempoutlines = []; $.each(this.lineout, function (index, line) { tempoutlines.push(line); }); $.each(tempoutlines, function (index, line) { line && line.removeElement(); }); var tempinlines = []; $.each(this.linein, function (index, line) { tempinlines.push(line); }); $.each(tempinlines, function (index, line) { line && line.removeElement(); }); }, removeOutLine: function (line) { var _that = this; $.each(this.lineout, function (index, elem) { if (elem && elem.id == line.id) { _that.lineout.splice(index, 1); } }) }, removeInLine: function (line) { var _that = this; $.each(this.linein, function (index, elem) { if (elem && elem.id == line.id) { _that.linein.splice(index, 1); } }) }, comeInSubProcess: function () { //判断是否在子流程里面 var parent = this.flow.collisionSubProcess(this.coordinate[0], this.coordinate[1], this.coordinate[2], this.coordinate[3]); //被碰撞 return parent; }, comeInSubProcess2: function (L, R, T, B) {//判断是否在子流程里面 var parent = this.flow.collisionSubProcess(L, R, T, B); //被碰撞 return parent; }, addParent: function (parent) {//在子流程里的处理 //判断落点是否在子流程内,如果落在子流程内,则需要修改parentElem if (!parent) { parent = this.flow.collisionSubProcess(this.coordinate[0], this.coordinate[1], this.coordinate[2], this.coordinate[3]); //被碰撞 } if (parent != null) { var ids = []; $.each(parent.subElement, function (index, elem) { ids.push(elem.id); }) if ($.inArray(this.id, ids) == -1) { this.parentElem = parent; parent.subElement.push(this); //表示新加入的到某个节点上,则原来的所有的线段需要移除 //移除相关的线 this.removeLine(); //节点置前 //this.element.toFront(); this.elementbox.toFront(); } } else {//没有父元素 if (this.parentElem) { this.parentElem.removeSubElement(this); this.parentElem = null; //表示新加入的到其他的,则原来子流程中的所有的线段需要移除 this.removeLine(); } } //return parent; }, getText: function () { return this.text.attr("text"); }, removeLine: function () { //删除线段 var tempoutlines = []; $.each(this.lineout, function (index, line) { if (!line.self) { tempoutlines.push(line); } }); $.each(tempoutlines, function (index, line) { line && line.removeElement(); if (line) { delete this.flow.alllines[line.id]; //删除线元素 } }); var tempinlines = []; $.each(this.linein, function (index, line) { if (!line.self) { tempinlines.push(line); } }); $.each(tempinlines, function (index, line) { line && line.removeElement(); if (line) { delete this.flow.alllines[line.id]; //删除线元素 } }); } }); function Line(flow, options) { this.flow = flow; //FlowDesigner类的实例 this.paper = flow.paper; //画布rapheal this.options = options; this.type = "line"; this.selected = false; this.id = options.id ? options.id : ""; this.isLoad = options.isLoad ? true : false; //是否是加载的元素 this.linetype = options.linetype ? options.linetype : 0; //元素 this.x1 = options.x1; //起点坐标x this.y1 = options.y1;//起点坐标y this.x2 = options.x2;//终点坐标x this.y2 = options.y2;//终点坐标y this.nodestart = options.nodestart; this.nodeend = options.nodeend; this.self = options.self; //起点和终点是否是同一个 //添加节点 this.linestr = ""; //线的字符串 this.line = null;//线 this.bbox = null; //线的外框 this.linebox = null; //线的可见外框 this.text = null; //线的文字 this.textPosWord = 0; //线上的文字向左偏移字的个数 this.linepoints = []; //线上的小圆点 this.linepointsxy = []; //线上的线段集合 this.content = {}; //线段数据 } Line.prototype = $.extend(Line.prototype, { init: function () { var linenumber = this.flow.createLineNum(); var tempName = (new Date()).getTime(); if (!this.isLoad) { this.id = "line_" + tempName; } //线 if (!this.self) { if (!this.isLoad) { //如果类型是双向,则需要画双箭头 if (this.linetype == 1) { var arrowPos = computeArrowPos(this.x2, this.y2, this.x1, this.y1); var x1a = arrowPos[0][0]; var y1a = arrowPos[0][1]; var x1b = arrowPos[1][0]; var y1b = arrowPos[1][1]; var result = ["M", this.x1, this.y1, "L", x1a, y1a, "M", this.x1, this.y1, "L", x1b, y1b, "M", this.x1, this.y1, "L", this.x2, this.y2]; this.linestr = result.join(","); } else { this.linestr = "M" + this.x1 + "," + this.y1 + "L" + this.x2 + "," + this.y2; } } else { this.linestr = this.options.linestr; } this.line = this.paper.path(this.linestr).attr({ "stroke-width": 2, "stroke": "#000000", "arrow-end": "open-wide", "cursor": "pointer", "stroke-linecap": "round", "stroke-linejoin": "round" }); this.bbox = this.line.getBBox(); //可见外框 this.linebox = this.paper.rect(this.bbox.x, this.bbox.y, this.bbox.width, this.bbox.height).attr({ "stroke-dasharray": "- ", "stroke": "#000000", "stroke-width": 0.5 }).hide(); //中间的圆点 if (!this.isLoad) { var centercircle = new SmallCircle(this.flow, this, {"cx": this.bbox.cx, "cy": this.bbox.cy}); centercircle.init(); this.linepoints.push(centercircle); this.linestr = "M" + this.x1 + "," + this.y1 + "L" + this.bbox.cx + "," + this.bbox.cy + "L" + this.x2 + "," + this.y2; this.linepointsxy = Raphael.parsePathString(this.linestr); } else { this.linepointsxy = Raphael.parsePathString(this.linestr); //如果类型是双向,则需要删除前面几个节点 if (this.linetype == 1) { this.linepointsxy.splice(0, 4); } //中间小圆点 for (var i = 1; i < this.linepointsxy.length - 1; i++) { var centercircle = new SmallCircle(this.flow, this, { "cx": this.linepointsxy[i][1], "cy": this.linepointsxy[i][2] }); centercircle.init(); this.linepoints.push(centercircle); } } //文字 中心节点 if (!this.isLoad) { this.text = this.paper.text(this.bbox.cx + 12, this.bbox.cy - 6, "线" + linenumber).attr({"font-size": "12px"}).toBack(); } else { //第一个小圆点的位置 if (this.linepoints.length > 0) { this.text = this.paper.text(this.linepoints[0].cx + 12, this.linepoints[0].cy - 6, this.options.text).attr({"font-size": "12px"}).toBack(); } else { this.text = this.paper.text(this.bbox.cx + 12, this.bbox.cy - 6, this.options.text).attr({"font-size": "12px"}).toBack(); } } } else { if (!this.isLoad) { //开始节点自身线 var x3 = this.x1; var y3 = this.y1 + this.nodestart.h * 1 / 4; var x4 = x3 - this.nodestart.w * 3 / 4; var y4 = y3; var x5 = x4; var y5 = y4 - this.nodestart.h * 3 / 4; this.linestr = "M" + this.x1 + "," + this.y1 + "L" + x3 + "," + y3 + "L" + x4 + "," + y4 + "L" + x5 + "," + y5 + "L" + this.x2 + "," + this.y2; } else { this.linestr = this.options.linestr; } this.line = this.paper.path(this.linestr).attr({ "stroke-width": 2, "stroke": "#000000", "arrow-end": "open-wide", "cursor": "pointer", "stroke-linecap": "round", "stroke-linejoin": "round" }); //外框 this.bbox = this.line.getBBox(); //可见外框 this.linebox = this.paper.rect(this.bbox.x, this.bbox.y, this.bbox.width, this.bbox.height).attr({ "stroke-dasharray": "- ", "stroke": "#000000", "stroke-width": 0.5 }).hide(); this.linepointsxy = Raphael.parsePathString(this.linestr); this.redrawSmallCircle(false); //文字 第一个小圆点 if (!this.isLoad) { this.text = this.paper.text(x3 + 12, y3, "线" + linenumber).attr({"font-size": "12px"}).toBack(); } else { this.text = this.paper.text(x3 + 12, y3, this.options.text).attr({"font-size": "12px"}).toBack(); } } //开始节点增加出去的线 this.nodestart && this.nodestart.lineout.push(this); //目标节点增加进入的线 this.nodeend && this.nodeend.linein.push(this); var _that = this; if (this.flow._DEFALUTS_.mode == "design") { //线的点击 this.line.click(function (event) { if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { _that.linebox.show(); //小菜单 $(".right").css({ "left": _that.bbox.x + _that.bbox.width + 10 - _that.flow.getScrollx(), "top": _that.bbox.y + _that.flow._DEFALUTS_.dy - _that.flow.getScrolly() }).attr("tempid", _that.id).end().find(".sequence").hide(); //显示线上的圆点 $.each(_that.linepoints, function (index, circle) { circle.element.show(); }); //显示两头节点上的圆心 _that.nodestart && _that.nodestart.ccelement.show(); _that.nodeend && _that.nodeend.ccelement.show(); _that.selected = true; //选中元素 var wenbenid = $(".taskinput input").attr("wenbenid"); if (wenbenid) { _that.setText(wenbenid); } _that.text.show(); } }); //线的双击 this.line.dblclick(function (e) { if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { var tvalue = _that.text.attr("text"); $(".taskinput input").val(tvalue); $(".taskinput input").attr("wenbenid", _that.id); //显示文本框 //线的宽度可能很细,需要取Max $(".taskinput").css({ "left": _that.bbox.cx - 15 - _that.flow.getScrollx(), "top": (_that.bbox.cy - 10 + _that.flow._DEFALUTS_.dy - _that.flow.getScrolly()), "width": Math.max(_that.bbox.width, 60) }); _that.selected = true; //文本框本身隐藏 _that.text.hide(); } }); this.line.mouseover(function () { //只有当lining状态为true时,使用 if (_that.flow.addPoint == true || _that.flow.subtractPoint == true) { //_that.linebox.show(); $.each(_that.linepoints, function (index, circle) { circle.element.show(); }); } }); } }, unSelect: function () { //非选中状态 //可见外框隐藏 this.linebox.hide(); //所有的线上的圆不显示 $.each(this.linepoints, function (index, circle) { circle.element.hide(); }); //文本框 if (this.selected == true) { var wenbenid = $(".taskinput input").attr("wenbenid"); if (wenbenid && wenbenid == this.id) { var value = $(".taskinput input").val(); value = $.trim(value); if (value) { this.setText(wenbenid); } else { this.setNullText(); } $(".taskinput input").attr("wenbenid", ""); } this.text.show(); } //文本框回归原位 $(".taskinput").css({"left": -100, "top": -100}); this.selected = false; }, removeElement: function () { this.line.remove(); this.linebox.remove(); this.text.remove(); //文本框回归 $(".taskinput").css({"left": -100, "top": -100}); //小圆点 $.each(this.linepoints, function (index, circle) { circle.removeElement(); }); this.nodestart && this.nodestart.removeOutLine(this); this.nodeend && this.nodeend.removeInLine(this); // //小菜单回归原位 $(".right").css({"left": -100, "top": -100}); }, redrawStart: function (startcx, startcy) { //开始坐标修改后,重绘 //重写线段 this.linestr = this.combPathFromStart(startcx, startcy); //找到合适的下一个点,作为目标点,做连线 this.line.attr("path", this.linestr); this.bbox = this.line.getBBox(); //外框 this.linebox.attr({ "x": this.bbox.x, "y": this.bbox.y, "width": this.bbox.width, "height": this.bbox.height }); //this.linestr = this.combPath(); //console.log("整理好后str", this.linestr); //根据坐标点重新渲染小圆点 this.redrawSmallCircle(false); //重绘文本位置 this.renderText(); }, redrawEnd: function (endcx, endcy) { //重写线段,endcx,endcy是中心点调整,重新计算开始坐标,需要得到箭头的坐标,如果中间点还在一条直线上,则还需要计算新的中间点坐标 this.linestr = this.combPathFromEnd(endcx, endcy); //console.log(this.linestr); this.line.attr("path", this.linestr); this.bbox = this.line.getBBox(); //外框 this.linebox.attr({ "x": this.bbox.x, "y": this.bbox.y, "width": this.bbox.width, "height": this.bbox.height }); //this.linestr = this.combPath(); //console.log("整理好后str", this.linestr); //根据坐标点重新渲染小圆点 this.redrawSmallCircle(false); //重绘文本位置 this.renderText(); }, linePointsDrag: function () { //线上的点拖动 var _that = this; $.each(this.linepoints, function (index, elem) { var circlecx = 0; var circlecy = 0; var circlepxindex = 0; elem.drag(function (tx, ty, x, y, e) { //拖动中 _lineCircleMove(tx, ty, x, y, e, _that, circlecx, circlecy, this, circlepxindex); }, function (x, y, e) { //开始 var bbox = this.getBBox(); //得到圆点的中心点坐标 circlecx = bbox.cx; circlecy = bbox.cy; circlepxindex = _lineCircleStart(x, y, e, _that, circlecx, circlecy); //console.log(circlepxindex); }, function (e) { //结束拖动 _lineCircleEnd(e, _that); }); }); }, combPath: function () { //通过线段集合重新组合path var path = ""; $.each(this.linepointsxy, function (index, elem) { path += elem[0] + elem[1] + "," + elem[2]; }) return path; }, combPathFromStart: function (nsx, nsy) { //通过线段集合重新组合path,从start出发 var path = ""; //判断相邻的两个点连成的直线,第三个点是否在上面,如果在,则把第二个点去掉,再判断第四个点是否在上面,如果在则把第三个点去掉,如果不在,则到第三个点位置。 //这个方法就是判断到两个点直线直到转折为止。 var temp = []; temp.push(["M", nsx, nsy]); //这个赋值只是个占位,后面还得改下 var x1 = this.linepointsxy[0][1]; var y1 = this.linepointsxy[0][2]; var x2 = this.linepointsxy[1][1]; var y2 = this.linepointsxy[1][2]; var zhixianindex = 1; var _that = this; var modifyNodes = []; //需要修改的小圆点的坐标 var modifyNodesIndexs = [];//需要修改的小圆点的位置 var length = this.linepointsxy.length; $.each(this.linepointsxy, function (index, elem) { if (index > 1) { if (floatToFix4(x1) != floatToFix4(x2)) { var y = _that.flow.getYLinePointFormula(x1, y1, x2, y2, elem[1]); //console.log(y,elem[2]) if (floatToFix4(y) == floatToFix4(elem[2])) { zhixianindex = index; modifyNodes.push(_that.linepointsxy[index - 1]); modifyNodesIndexs.push(index - 1); } else { return false; } } else { var x = _that.flow.getXLinePointFormula(x1, y1, x2, y2, elem[2]); //console.log(x,elem[1]) if (floatToFix4(x) == floatToFix4(elem[1])) { zhixianindex = index; modifyNodes.push(_that.linepointsxy[index - 1]); modifyNodesIndexs.push(index - 1); } else { return false; } } } }); //zhixianindex的值当等于最后一个节点时,重新计算箭头节点 if (zhixianindex == length - 1) { if (this.nodeend.type == "end") { var arrow = this.flow.getCircleArrowPosXY(this.nodestart, this.nodeend); } else if (this.nodeend.type == "gateway") { var arrow = this.flow.getGatewayArrowPosXY(this.nodestart, this.nodeend); } else if (this.nodeend.type == "userTask" || this.nodeend.type == "subProcess") { var arrow = this.flow.getArrowPosXY(this.nodestart, this.nodeend); } this.linepointsxy[length - 1][1] = arrow.x; this.linepointsxy[length - 1][2] = arrow.y; } if (zhixianindex == length - 1) { var tempEnd = this.nodeend; } else { tempEnd = this.linepoints[zhixianindex - 1]; } //重新计算开始节点 var startPoint = flowDesigner.getStartPosXY(this.nodestart, tempEnd); this.x1 = startPoint.x; this.y1 = startPoint.y; this.linepointsxy[0][1] = startPoint.x; this.linepointsxy[0][2] = startPoint.y; temp[0] = ["M", startPoint.x, startPoint.y]; $.each(this.linepointsxy, function (index, elem) { if (index >= zhixianindex) { temp.push(elem); } }); if (modifyNodes.length > 0) { //根据坐标修改小圆点 this.modifyLineCircle(modifyNodes, modifyNodesIndexs, startPoint, {"x": temp[1][1], "y": temp[1][2]}); } //如果节点类型是1,则表明是双向,需要画双箭头 if (this.content && this.content.nodeType && this.content.nodeType == "1") { var arrowPos = computeArrowPos(temp[1][1], temp[1][2], temp[0][1], temp[0][2]); var x1a = arrowPos[0][0]; var y1a = arrowPos[0][1]; var x1b = arrowPos[1][0]; var y1b = arrowPos[1][1]; temp.splice(1, 0, ["L", x1a, y1a], ["M", startPoint.x, startPoint.y], ["L", x1b, y1b], ["M", startPoint.x, startPoint.y]); } $.each(temp, function (index, elem) { path += elem[0] + elem[1] + "," + elem[2]; }); return path; }, combPathFromEnd: function (nex, ney) { //通过线段集合重新组合path,从end向上找出合适的出发点,和新的目的中心点连接,找出箭头点。 var path = ""; //判断相邻的两个点连成的直线,第三个点是否在上面,如果在,则把第二个点去掉,再判断第四个点是否在上面,如果在则把第三个点去掉,如果不在,则到第三个点位置。 //这个方法就是判断到两个点直线直到转折为止。 var temp = []; var length = this.linepointsxy.length; temp.push(["L", nex, ney]); //这个赋值只是个占位,最终箭头的nex和ney还是要计算获得 var x1 = this.linepointsxy[length - 1][1]; var y1 = this.linepointsxy[length - 1][2]; var x2 = this.linepointsxy[length - 2][1]; var y2 = this.linepointsxy[length - 2][2]; var zhixianindex = length - 2; var _that = this; var modifyNodes = []; //需要修改的小圆点的坐标 var modifyNodesIndexs = [];//需要修改的小圆点的位置 //console.log(_that.linepointsxy); for (var i = length - 3; i >= 0; i--) { //console.log(x1, y1, x2, y2, _that.linepointsxy[i][1]); if (floatToFix4(x1) != floatToFix4(x2)) { //求y值时,会出现x1-x2为0的情况 var y = _that.flow.getYLinePointFormula(x1, y1, x2, y2, _that.linepointsxy[i][1]); //console.log(floatToFix4(y) ,floatToFix4(_that.linepointsxy[i][2])); if (floatToFix4(y) == floatToFix4(_that.linepointsxy[i][2])) { zhixianindex = i; modifyNodes.unshift(_that.linepointsxy[i + 1]); //向前插入 modifyNodesIndexs.unshift(i + 1); } else { break; } } else {//求y值时,会出现x1-x2为0的情况,当出现时,求x值,来进行判断 var x = _that.flow.getXLinePointFormula(x1, y1, x2, y2, _that.linepointsxy[i][2]); if (floatToFix4(x) == floatToFix4(_that.linepointsxy[i][1])) { zhixianindex = i; modifyNodes.unshift(_that.linepointsxy[i + 1]); modifyNodesIndexs.unshift(i + 1); } else { break; } } } // $.each(this.linepointsxy, function (index, elem) { // if (index >= zhixianindex) { // temp.unshift(elem); // } // }); for (var i = zhixianindex; i >= 0; i--) { temp.unshift(_that.linepointsxy[i]); } //根据两点得到箭头坐标 //1.首先得到是从哪个小圆点出发的 var nearx = temp[temp.length - 2][1]; var neary = temp[temp.length - 2][2]; var source = null; $.each(this.linepoints, function (index, circle) { if (floatToFix4(nearx) == floatToFix4(circle.cx) && floatToFix4(neary) == floatToFix4(circle.cy)) { source = circle; return false; } }); if (source == null) { source = this.nodestart; //修改开始节点 var startPoint = flowDesigner.getStartPosXY(source, this.nodeend); this.x1 = startPoint.x; this.y1 = startPoint.y; this.linepointsxy[0][1] = startPoint.x; this.linepointsxy[0][2] = startPoint.y; temp[0][1] = startPoint.x; temp[0][2] = startPoint.y; } switch (this.nodeend.type) { case "end": arrow = this.flow.getCircleArrowPosXY(source, this.nodeend); break; case "gateway": arrow = this.flow.getGatewayArrowPosXY(source, this.nodeend); break; case "subProcess": case "userTask": arrow = this.flow.getArrowPosXY(source, this.nodeend); break; } //console.log("arrow",arrow); temp[temp.length - 1][1] = arrow.x; temp[temp.length - 1][2] = arrow.y; //console.log("modifyNodes",modifyNodes); if (modifyNodes.length > 0) { //根据坐标修改小圆点 this.modifyLineCircle(modifyNodes, modifyNodesIndexs, { "x": temp[temp.length - 2][1], "y": temp[temp.length - 2][2] }, {"x": arrow.x, "y": arrow.y}); } this.linepointsxy[length - 1][1] = arrow.x; this.linepointsxy[length - 1][2] = arrow.y; this.x2 = arrow.x; this.y2 = arrow.y; //如果节点类型是1,则表明是双向,需要画双箭头 if (this.content && this.content.nodeType && this.content.nodeType == "1") { var arrowPos = computeArrowPos(temp[1][1], temp[1][2], temp[0][1], temp[0][2]); var x1a = arrowPos[0][0]; var y1a = arrowPos[0][1]; var x1b = arrowPos[1][0]; var y1b = arrowPos[1][1]; temp.splice(1, 0, ["L", x1a, y1a], ["M", startPoint.x, startPoint.y], ["L", x1b, y1b], ["M", startPoint.x, startPoint.y]); } $.each(temp, function (index, elem) { path += elem[0] + elem[1] + "," + elem[2]; }); return path; }, //修改线上的小圆点的坐标, modifypoints需要修改的小圆点,modifyNodesIndexs需要修改的小圆点的在linepointsxy的索引,startpoint 线上的开始节点,endpoint 线上的结束节点 modifyLineCircle: function (modifypoints, modifyNodesIndexs, startpoint, endpoint) { var length = modifypoints.length; var newPoint; //console.log("startpoint",startpoint); //console.log("endpoint",endpoint); for (var i = 0; i < length; i++) { //循环需要修改的小圆点 // nx = (startpoint.x + endpoint.x) * (i + 1) / (length + 1); // ny = (startpoint.y + endpoint.y) * (i + 1) / (length + 1); newPoint = this.flow.getNewSmallCirclePosXY(startpoint, endpoint, modifypoints, length + 1, i + 1); //得到新的坐标的值 var _that = this; _that.linepointsxy[modifyNodesIndexs[i]][1] = newPoint.x; _that.linepointsxy[modifyNodesIndexs[i]][2] = newPoint.y; // $.each(this.linepoints, function (index, circle) { // if (floatToFix4(modifypoints[i][1]) == floatToFix4(circle.cx) && floatToFix4(modifypoints[i][2]) == floatToFix4(circle.cy)) { // //circle.element.attr({ "cx": nx, "cy": ny }); // circle.render({ "cx": newPoint.x, "cy": newPoint.y }); // console.log("新坐标", newPoint.x, newPoint.y); // console.log(_that.linepointsxy); // console.log("所在位置", modifyNodesIndexs[i]); // _that.linepointsxy[modifyNodesIndexs[i]][1] = newPoint.x; // _that.linepointsxy[modifyNodesIndexs[i]][2] = newPoint.y; // } // }); } }, currentPointInPathIndex: function (x, y) { //当前节点在线段上的所属位置 var curIndex = 0; //console.log("当前节点在线段上的所属位置", this.linepointsxy); $.each(this.linepointsxy, function (index, elem) { if (floatToFix4(elem[1]) == floatToFix4(x) && floatToFix4(elem[2]) == floatToFix4(y)) { curIndex = index; return false; } }); return curIndex; }, //重绘线上所有的小圆点 show:true表示小圆点显示 redrawSmallCircle: function (show) { //先去掉线上的小圆点 $.each(this.linepoints, function (index, circle) { circle.removeElement(); }); this.linepoints = []; //重新获取设置线上的小圆点 var newlength = this.linepointsxy.length; _that = this; $.each(this.linepointsxy, function (index, arr) { if (index > 0 && index < newlength - 1) { //去掉头尾两个小圆点 //生成小圆点 var tempCircle = new SmallCircle(_that.flow, _that, {"cx": arr[1], "cy": arr[2], "show": show}); tempCircle.init(); _that.linepoints.push(tempCircle); } }); }, //删除线上的小圆点 removeSmallCircle: function (circle) { if (this.linepoints.length <= 1) { $.messager.alert("删除线上小圆点-提示", "当线段只有唯一一个小圆点时,该小圆点不能被删除!"); return false; } var deleindex = 0; var oldlength = this.linepointsxy.length; $.each(this.linepointsxy, function (index, attr) { if (floatToFix4(circle.cx) == floatToFix4(attr[1]) && floatToFix4(circle.cy) == floatToFix4(attr[2])) { deleindex = index; return false; } }); this.linepointsxy.splice(deleindex, 1); var newlength = this.linepointsxy.length; var _that = this; if (deleindex == oldlength - 2) { //重新计算箭头节点 var source = null; if (newlength == 2) { source = this.nodestart; } else { $.each(this.linepoints, function (index, elem) { if (floatToFix4(_that.linepointsxy[newlength - 2][1]) == floatToFix4(elem.cx) && floatToFix4(_that.linepointsxy[newlength - 2][2]) == floatToFix4(elem.cy)) { source = elem; } }); } if (this.nodeend.type == "end") { var arrow = this.flow.getCircleArrowPosXY(source, this.nodeend); } else if (this.nodeend.type == "gateway") { var arrow = this.flow.getGatewayArrowPosXY(source, this.nodeend); } else if (this.nodeend.type == "userTask" || this.nodeend.type == "subProcess") { var arrow = this.flow.getArrowPosXY(source, this.nodeend); } this.linepointsxy[newlength - 1][1] = arrow.x; this.linepointsxy[newlength - 1][2] = arrow.y; } this.linestr = Raphael.parsePathString(this.linepointsxy); //重绘小圆点 this.redrawSmallCircle(true); //this.linepoints的改变在线段的重绘小圆点里面 //重新画线 this.line.attr("path", this.linestr); }, //重绘文本位置 renderText: function () { //跟着小圆点的位置,如果有小圆点,就跟着第一个小圆点,如果没有去中心点 if (this.linepoints.length > 0) { this.text.attr({"x": this.linepoints[0].cx + 12, "y": this.linepoints[0].cy - 6}) } else { this.bbox = this.line.getBBox(); this.text.attr({"x": this.bbox.cx + 12, "y": this.bbox.cy - 6}); } }, setNullText: function () { this.text.attr({"text": ""}); }, setText: function (wenbenid) { //得到文本框的值,重新赋值给text //Raphaël\nkicks\nbutt! var tvalue = $(".taskinput input").val(); var temp = tvalue; if ($.trim(tvalue) != "" && wenbenid == this.id) { var zishu = Math.floor(Math.max(this.bbox.width, 60) / 12); //一行可显示的中文字数 var hangshu = parseInt(tvalue.length / zishu) + 1; //行数 var arr = []; if (tvalue.length > zishu) { for (var j = 0; j < hangshu; j++) { for (var i = j * zishu; i < (j + 1) * zishu; i = i + 1) { if (tvalue[i]) { if (arr[j]) { arr[j] += tvalue[i]; } else { arr[j] = tvalue[i]; } } } } temp = arr.join('\n'); } this.text.attr({"text": temp}); $(".taskinput input").val("");//清空 } }, getText: function () { return this.text.attr("text"); }, //移动节点含有自身线时,重绘 renderMoveSelf: function () { //开始节点自身线 this.x1 = this.nodestart.centerpoint[0]; this.y1 = this.nodestart.centerpoint[1] + this.nodestart.h / 2; this.x2 = this.nodestart.x; this.y2 = this.nodestart.centerpoint[1]; var x3 = this.x1; var y3 = this.y1 + this.nodestart.h * 1 / 4; var x4 = x3 - this.nodestart.w * 3 / 4; var y4 = y3; var x5 = x4; var y5 = y4 - this.nodestart.h * 3 / 4; this.linestr = "M" + this.x1 + "," + this.y1 + "L" + x3 + "," + y3 + "L" + x4 + "," + y4 + "L" + x5 + "," + y5 + "L" + this.x2 + "," + this.y2; this.linepointsxy = []; this.linepointsxy = Raphael.parsePathString(this.linestr); this.render2(); }, recalculatePath: function () { //重新计算路径 if (!this.self) { this.redrawStart(this.x1, this.y1); } else { this.renderMoveSelf(); } }, render2: function () {//重绘线段 this.line.attr("path", this.linestr); //外框 this.bbox = this.line.getBBox(); //可见外框 this.linebox.attr({ "x": this.bbox.x, "y": this.bbox.y, "width": this.bbox.width, "height": this.bbox.height }); //线上原来的小圆点删除 for (var i = 0; i < this.linepoints.length; i++) { this.linepoints[i].removeElement(); } this.linepoints = []; //中间小圆点 for (var i = 1; i < this.linepointsxy.length - 1; i++) { var centercircle = new SmallCircle(this.flow, this, { "cx": this.linepointsxy[i][1], "cy": this.linepointsxy[i][2] }); centercircle.init(); this.linepoints.push(centercircle); } this.renderText(); } }); //计算自定义箭头坐标 function computeArrowPos(x1, y1, x2, y2) { var angle = Raphael.angle(x1, y1, x2, y2);//得到两点之间的角度 var a45 = Raphael.rad(angle - 30);//角度转换成弧度 var a45m = Raphael.rad(angle + 30); var x1a = x2 + Math.cos(a45) * 10; var y1a = y2 + Math.sin(a45) * 10; var x1b = x2 + Math.cos(a45m) * 10; var y1b = y2 + Math.sin(a45m) * 10; return [[x1a, y1a], [x1b, y1b]]; } //线上的小圆点 function SmallCircle(flow, belongLine, options) { this.flow = flow; //FlowDesigner类 this.paper = flow.paper; this.belongLine = belongLine; this.type = "smallcircle"; this.options = options; this.id = ""; this.element = null; //start圆 this.bbox = null; //圆的真实外框 this.coordinate = []; //圆元素的上下左右坐标 //元素 this.cx = options.cx; this.cy = options.cy; this.centerpoint = [this.cx, this.cy]; this.r = 3; this.show = options.show; } SmallCircle.prototype = $.extend(SmallCircle.prototype, { init: function () { var number = this.flow.createSmallCircleNodeNum(); var tempName = (new Date()).getTime(); this.id = "smallcircle_" + tempName; //圆 this.element = this.paper.circle(this.cx, this.cy, this.r).attr({ "fill": "#ff00ff", "cursor": "move" }).hide(); if (this.show) { this.element.show(); } this.centerpoint = [this.cx, this.cy]; //真外框 this.bbox = this.element.getBBox(); //坐标(L,R,T,B) this.coordinate.push(this.bbox.x, this.bbox.x + this.bbox.width, this.bbox.y, this.bbox.y + this.bbox.height); var _that = this; //圆点的移动 var circlecx = 0; var circlecy = 0; var circlepxindex = 0; var weiyiX = 0; var weiyiY = 0; var bpzcenter = null; this.element.drag(function (tx, ty, x, y, e) { //move if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { var currentX = circlecx + tx; var currentY = circlecy + ty; //碰撞自身的中心线 var L = e.clientX - _that.flow._DEFALUTS_.dx - weiyiX; var R = L + _that.r * 2; var T = e.clientY - _that.flow._DEFALUTS_.dy - weiyiY; var B = T + _that.r * 2; bpzcenter = _that.flow.collisionSelfCenterLine(_that, L, R, T, B); //中心线匹配 if (bpzcenter[0] != null) { currentX = bpzcenter[0]; } if (bpzcenter[1] != null) { currentY = bpzcenter[1]; } _that.belongLine.linepointsxy[circlepxindex][1] = currentX; _that.belongLine.linepointsxy[circlepxindex][2] = currentY; //重写线段 _that.belongLine.linestr = _that.belongLine.combPath(); _that.belongLine.line.attr("path", _that.belongLine.linestr); //修改text坐标 _that.belongLine.renderText(); //自身渲染,这个渲染可能包含重绘线段开始和结束坐标 _that.render({"cx": currentX, "cy": currentY}); } }, function (x, y, e) { //start //得到圆点的中心点坐标 if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { circlecx = _that.bbox.cx; circlecy = _that.bbox.cy; circlepxindex = _that.belongLine.currentPointInPathIndex(circlecx, circlecy); weiyiX = e.clientX - _that.flow._DEFALUTS_.dx - _that.bbox.x;//offsetX,不需要减1 weiyiY = e.clientY - _that.flow._DEFALUTS_.dy - _that.bbox.y; //offsetY,不需要减32 } }, function (e) { //end if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { _that.belongLine.bbox = _that.belongLine.line.getBBox(); _that.belongLine.linebox.attr({ "x": _that.belongLine.bbox.x, "y": _that.belongLine.bbox.y, "width": _that.belongLine.bbox.width, "height": _that.belongLine.bbox.height }); _that.belongLine.linepointsxy = Raphael.parsePathString(_that.belongLine.linestr); } }) //小圆点双击减点自身 this.element.dblclick(function () { if (_that.flow.subtractPoint == true) { _that.belongLine.removeSmallCircle(_that); } }); }, render: function (options) { //小圆点 this.cx = options.cx; this.cy = options.cy; this.centerpoint = [this.cx, this.cy]; this.element.attr({"cx": this.cx, "cy": this.cy}); this.centerpoint = [this.cx, this.cy]; //真外框 this.bbox = this.element.getBBox(); //坐标(L,R,T,B) this.coordinate = []; this.coordinate.push(this.bbox.x, this.bbox.x + this.bbox.width, this.bbox.y, this.bbox.y + this.bbox.height); //如果该点是连接线段是两个节点,则需要重绘开始节点和箭头节点 var length = this.belongLine.linepointsxy.length; var circlepxindex = this.belongLine.currentPointInPathIndex(this.cx, this.cy); if (circlepxindex == 1) { //重绘开始节点 var startPoint = flowDesigner.getStartPosXY(this.belongLine.nodestart, this); this.belongLine.x1 = startPoint.x; this.belongLine.y1 = startPoint.y; this.belongLine.linepointsxy[0][1] = startPoint.x; this.belongLine.linepointsxy[0][2] = startPoint.y; } if (length == 3 || circlepxindex == length - 2) { //重绘结束节点 switch (this.belongLine.nodeend.type) { case "end": var arrow = this.flow.getCircleArrowPosXY(this, this.belongLine.nodeend); break; case "gateway": arrow = this.flow.getGatewayArrowPosXY(this, this.belongLine.nodeend); break; case "subProcess": case "userTask": arrow = this.flow.getArrowPosXY(this, this.belongLine.nodeend); break; } this.belongLine.x2 = arrow.x; this.belongLine.y2 = arrow.y; this.belongLine.linepointsxy[length - 1][1] = arrow.x; this.belongLine.linepointsxy[length - 1][2] = arrow.y; } this.belongLine.linestr = this.belongLine.combPath(); this.belongLine.line.attr("path", this.belongLine.linestr); }, removeElement: function () { this.element.remove(); delete this; } }); function End(flow, options) { this.flow = flow; //FlowDesigner类 this.paper = flow.paper; //画布 this.options = options; this.type = "end"; this.selected = false; this.id = options.id ? options.id : ""; this.isLoad = options.isLoad ? true : false; //是否是加载的元素 this.parentElem = null; //所属父级 this.parentElemStr = options.parentElem; //加载时所属父级的名称 this.element = null; //start圆 this.bmargin = 4; //外框和元素的边距 this.elementbox = null; //start圆的外框,加厚边距 this.bbox = null; //圆的真实外框 //this.$moveDiv=null; //外框拖动虚框 this.coordinate = []; //圆元素的上下左右四条边坐标 this.centerLineCoordinate = []; //圆元素的上下左右四条边坐标,为显示中心线,小一点 this.centerMargin = 10; //向中心点向外4个方向扩展的距离 this.centerLineX = null; this.centerLineY = null; //元素 this.cx = options.cx; this.cy = options.cy; this.centerpoint = [this.cx, this.cy]; this.r = options.r; this.ccelement = null; //圆心 this.linein = []; //所有的有关进入的线 this.text = null; //文本 this.content = {}; //结束节点内容 this.completeState = options.completeState || 0; //0 代表否 1代表已完 2代表正当 3代表还未开始 } End.prototype = $.extend(End.prototype, { init: function () { var number = this.flow.createEndNodeNum(); var tempName = (new Date()).getTime(); if (!this.isLoad) { this.id = "end_" + tempName; } //圆 switch (this.completeState) { case 1: //蓝色 this.element = this.paper.circle(this.cx, this.cy, this.r).attr({ "fill": "#e0e9fe", "cursor": "pointer", "stroke": "#2632aa", "stroke-width": 3 }); break; case 2://绿色 this.element = this.paper.circle(this.cx, this.cy, this.r).attr({ "fill": "#ebf8eb", "cursor": "pointer", "stroke": "#017501", "stroke-width": 3 }); break; case 3://灰色 this.element = this.paper.circle(this.cx, this.cy, this.r).attr({ "fill": "#dadada", "cursor": "pointer", "stroke": "#acacac", "stroke-width": 3 }); break; default: this.element = this.paper.circle(this.cx, this.cy, this.r).attr({ "fill": "#ffffff", "stroke-width": 3, "cursor": "pointer" }); break; } this.centerpoint = [this.cx, this.cy]; this.ccelement = this.paper.circle(this.centerpoint[0], this.centerpoint[1], 2).attr({ "fill": "#ff0000", "stroke": "ff0000" }).hide(); //圆心 //end真外框 this.bbox = this.element.getBBox(); //end扩大的外框 this.elementbox = this.paper.rect(this.bbox.x - this.bmargin, this.bbox.y - this.bmargin, this.bbox.width + this.bmargin * 2, this.bbox.height + this.bmargin * 2).attr({ "stroke-dasharray": "- ", "stroke": "#000000", "stroke-width": 0.5, "fill": "#ff0000", "fill-opacity": 0 }); //坐标(L,R,T,B) this.coordinate.push(this.bbox.x, this.bbox.x + this.bbox.width, this.bbox.y, this.bbox.y + this.bbox.height); //中心点向外扩展centerMargin=10,得到4条边,坐标(L,R,T,B) this.centerLineCoordinate.push(this.centerpoint[0] - this.centerMargin, this.centerpoint[0] + this.centerMargin, this.centerpoint[1] - this.centerMargin, this.centerpoint[1] + this.centerMargin); //文字 if (!this.isLoad) { this.text = this.paper.text(this.centerpoint[0], this.centerpoint[1] + this.r + 12, "结束" + number).attr({"font-size": "12px"}).toBack(); } else { this.text = this.paper.text(this.centerpoint[0], this.centerpoint[1] + this.r + 12, this.options.text).attr({"font-size": "12px"}).toBack(); } //隐藏的中心竖线 this.centerLineY = this.paper.path("M" + this.centerpoint[0] + ",0L" + this.centerpoint[0] + "," + this.flow._DEFALUTS_.height).attr({ "stroke-width": 2, "stroke": "#c1c1c1", "stroke-dasharray": "- " }).hide(); //隐藏的中心横线 this.centerLineX = this.paper.path("M0," + this.centerpoint[1] + "L" + this.flow._DEFALUTS_.width + "," + this.centerpoint[1]).attr({ "stroke-width": 2, "stroke": "#c1c1c1", "stroke-dasharray": "- " }).hide(); //添加父元素 if (!this.isLoad) { this.addParent(); } var _that = this; //end圆的外框点击 if (this.completeState == 0) { this.elementbox.click(function (e) { //小菜单 $(".right").css({ "left": _that.cx + _that.r + 10 - _that.flow.getScrollx(), "top": _that.cy - _that.r + _that.flow._DEFALUTS_.dy - _that.flow.getScrolly() }).attr("tempid", _that.id).end().find(".sequence").hide(); //显示外框 _that.selected = true; //选中元素 var wenbenid = $(".taskinput input").attr("wenbenid"); if (wenbenid) { _that.setText(wenbenid); } _that.text.show(); }); //end圆的外框双击 this.elementbox.dblclick(function (e) { if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { var tvalue = _that.text.attr("text"); $(".taskinput input").val(tvalue); $(".taskinput input").attr("wenbenid", _that.id); //显示文本框 $(".taskinput").css({ "left": _that.cx - _that.r - 15 - _that.flow.getScrollx(), "top": (_that.cy - 10 + _that.flow._DEFALUTS_.dy - _that.flow.getScrolly()), "width": 60 }); _that.selected = true; //文本框本身隐藏 _that.text.hide(); } }); //end圆的点击元素 this.element.click(function (e) { _that.elementbox.show(); $(".right").css({ "left": _that.cx + _that.r + 10 - _that.flow.getScrollx(), "top": _that.cy - _that.r + _that.flow._DEFALUTS_.dy - _that.flow.getScrolly() }).attr("tempid", _that.id).end().find(".sequence").hide(); //这个8,是为了对齐随便写的 }); //end圆的外层框拖动 var weiyiX = 0; var weiyiY = 0; var dropStatus = false; var startX = 0; var startY = 0; var bpz = null; var bpzcenter = null; this.elementbox.drag(function (tx, ty, x, y, e) { //move中 dropStatus = true; //限制去菜单那块 if (e.clientX < (134 + _that.flow._DEFALUTS_.dx + weiyiX)) { e.clientX = 134 + _that.flow._DEFALUTS_.dx; dropStatus = false; return; } //限制画布最右侧边界 if (e.clientX > _that.flow._DEFALUTS_.width - (_that.r + _that.bmargin) * 2 + _that.flow._DEFALUTS_.dx + weiyiX) { dropStatus = false; return; } //限制头部 if (e.clientY < (0 + _that.flow._DEFALUTS_.dy + weiyiY)) { e.clientY = 0 + _that.flow._DEFALUTS_.dy; dropStatus = false; return; } //限制画布底部边界 if (e.clientY > (0 + _that.flow._DEFALUTS_.height - (_that.r + _that.bmargin) * 2 + _that.flow._DEFALUTS_.dy + weiyiY)) { dropStatus = false; return; } this.attr({ "x": e.clientX - _that.flow._DEFALUTS_.dx - weiyiX, "y": e.clientY - _that.flow._DEFALUTS_.dy - weiyiY }); //碰撞检测 var L = e.clientX - _that.flow._DEFALUTS_.dx - weiyiX; var R = L + _that.r * 2; var T = e.clientY - _that.flow._DEFALUTS_.dy - weiyiY; var B = T + _that.r * 2; bpz = _that.flow.collision(_that, L, R, T, B); //被碰撞 if (bpz != null && bpz.type != "subProcess") { dropStatus = false; } bpzcenter = _that.flow.collisionCenterLine(_that, L, R, T, B); //中心线匹配 }, function (x, y, e) { //move开始 weiyiX = e.clientX - _that.flow._DEFALUTS_.dx - _that.bbox.x + _that.bmargin; //offsetX,不需要减1 weiyiY = e.clientY - _that.flow._DEFALUTS_.dy - _that.bbox.y + _that.bmargin; //offsetY,不需要减32 startX = _that.bbox.x - _that.bmargin; startY = _that.bbox.y - _that.bmargin; }, function (e) {//move结束 if (dropStatus == true) { var elemnetboxbbox = this.getBBox(); var cx = elemnetboxbbox.cx; var cy = elemnetboxbbox.cy; //判断是否进入子流程 if (bpz && bpz.type == "subProcess") { //说明进入在子流程中 if (_that.parentElem == null || _that.parentElem.id != bpz.id) { //表示新的入到一个子流程中 if (_that.linein.length > 0) { //如果含有线段,则必须提示,因为进入新的空间,旧的空间中的线段需要删除 $.messager.confirm('再次确认', '该结束节点进入子流程会删除原来的线段,还要继续进入吗?', function (r) { if (!r) { _that.elementbox.attr({"x": startX, "y": startY}); //不能落下的地方就返回 } else { _that.render(cx, cy, bpzcenter); } }) } else { //没有线段 _that.render(cx, cy, bpzcenter); } } } else if (bpz == null) { if (_that.parentElem != null) { //原来在小空间中 if (_that.linein.length > 0) { //如果含有线段,则必须提示,因为进入新的空间,旧的空间中的线段需要删除 var L = elemnetboxbbox.x; var R = L + _that.r * 2; var T = elemnetboxbbox.y; var B = T + _that.r * 2; //判断当前是否已经出了小空间 if (!_that.comeInSubProcess2(L, R, T, B)) { $.messager.confirm('再次确认', '该结束节点原属于子流程空间,进入父空间时会删除原来的线段,还要继续进入吗?', function (r) { if (!r) { _that.elementbox.attr({"x": startX, "y": startY}); //不能落下的地方就返回 } else { _that.render(cx, cy, bpzcenter); } }) } else { //没有出小空间 _that.render(cx, cy, bpzcenter); } } else { //没有线段 _that.render(cx, cy, bpzcenter); } } else { //原来在大空间中 _that.render(cx, cy, bpzcenter); } } } else { this.attr({"x": startX, "y": startY}); //不能落下的地方就返回 } dropStatus = false; return false; }); } else if (this.completeState == 1 || this.completeState == 2) { this.element.mouseover(function (e) { $("[id*=divshow_]").hide(); var wheight = e.view.innerHeight; //屏幕大小 var wheight2 = Math.floor(wheight / 2);//屏幕大小的一半 var name = "divshow_" + _that.id; if ($("#" + name).length == 0) { //创建 if (e.pageY <= wheight2) { var str = "

" + _that.getText() + "

"; } else { var str = "

" + _that.getText() + "

"; } if (_that.completeState == 1) { str += "

已办理

"; if (_that.content.activityUsers && _that.content.activityUsers.length > 0) { $.each(_that.content.activityUsers, function (i, el) { str += "

办理人员" + el.name + "办理时间" + el.time + "

办理意见" + el.advice + "

"; }) } } else if (_that.completeState == 2) { if (_that.content.waitActivityUsers && _that.content.waitActivityUsers.length > 0) { str += "

正在办理

"; $.each(_that.content.waitActivityUsers, function (i, el) { str += "

办理人员" + el.name + "开始时间" + el.time + "

"; }) } if (_that.content.activityUsers && _that.content.activityUsers.length > 0) { str += "

已办理

"; $.each(_that.content.activityUsers, function (i, el) { str += "

办理人员" + el.name + "办理时间" + el.time + "

办理意见" + el.advice + "

"; }) } } str += "
"; $("#" + _that.flow._DEFALUTS_.id).append(str); } else { if (e.pageY <= wheight2) { $("#" + name).css({"left": (e.pageX + 0), "top": (e.pageY + 0), "bottom": "auto"}).show(); $("#" + name).find(".con").css({"maxHeight": wheight2}); } else { $("#" + name).css({ "left": (e.pageX + 0), "bottom": (wheight - e.pageY + 0), "top": "auto" }).show(); $("#" + name).find(".con").css({"maxHeight": wheight2}); } } }) } }, render: function (cx, cy, bpzcenter) { //end渲染 if (bpzcenter != null) { //碰撞吸附 if (bpzcenter[0] != null && bpzcenter[1] == null) { //y轴吸附,x轴不吸附 if (bpzcenter[0].type == "start" || bpzcenter[0].type == "end" || bpzcenter[0].type == "gateway") { cx = bpzcenter[0].cx; } else if (bpzcenter[0].type == "userTask" || bpzcenter[0].type == "subProcess") { cx = bpzcenter[0].x + bpzcenter[0].w / 2; } } else if (bpzcenter[0] == null && bpzcenter[1] != null) { //x轴吸附,y轴不吸附 if (bpzcenter[1].type == "start" || bpzcenter[1].type == "end" || bpzcenter[1].type == "gateway") { cy = bpzcenter[1].cy; } else if (bpzcenter[1].type == "userTask" || bpzcenter[1].type == "subProcess") { cy = bpzcenter[1].y + bpzcenter[1].h / 2; } } else if (bpzcenter[0] != null && bpzcenter[1] != null) { //y轴吸附,x轴吸附 if (bpzcenter[0].type == "start" || bpzcenter[0].type == "end" || bpzcenter[0].type == "gateway") { cx = bpzcenter[0].cx; } else if (bpzcenter[0].type == "userTask" || bpzcenter[0].type == "subProcess") { cx = bpzcenter[0].x + bpzcenter[0].w / 2; } if (bpzcenter[1].type == "start" || bpzcenter[1].type == "end" || bpzcenter[1].type == "gateway") { cy = bpzcenter[1].cy; } else if (bpzcenter[1].type == "userTask" || bpzcenter[1].type == "subProcess") { cy = bpzcenter[1].y + bpzcenter[1].h / 2; } } } //end圆的重新渲染 this.cx = cx; this.cy = cy; this.element.attr({"cx": cx, "cy": cy}); this.bbox = this.element.getBBox(); this.centerpoint = [cx, cy]; //扩大的外框 this.elementbox.attr({"x": this.bbox.x - this.bmargin, "y": this.bbox.y - this.bmargin}); //修改坐标(L,R,T,B) this.coordinate[0] = this.bbox.x; this.coordinate[1] = this.bbox.x + this.bbox.width; this.coordinate[2] = this.bbox.y; this.coordinate[3] = this.bbox.y + this.bbox.height; //圆心 this.ccelement.attr({"cx": this.centerpoint[0], "cy": this.centerpoint[1]}); //中心点向外扩展centerMargin=10,得到4条边,坐标(L,R,T,B) this.centerLineCoordinate = []; this.centerLineCoordinate.push(this.centerpoint[0] - this.centerMargin, this.centerpoint[0] + this.centerMargin, this.centerpoint[1] - this.centerMargin, this.centerpoint[1] + this.centerMargin); //文字 this.text.attr({"x": this.centerpoint[0], "y": this.centerpoint[1] + this.r + 12}); //移动隐藏的中心竖线 this.centerLineY.attr("path", "M" + this.centerpoint[0] + ",0L" + this.centerpoint[0] + "," + this.flow._DEFALUTS_.height); //移动隐藏的中心横线 this.centerLineX.attr("path", "M0," + this.centerpoint[1] + "L" + this.flow._DEFALUTS_.width + "," + this.centerpoint[1]); var _that = this; //所有进入的线,因为坐标变了,需要重绘 $.each(this.linein, function (index, lineElem) { lineElem.redrawEnd(_that.cx, _that.cy); }); //父元素处理 var parent = this.comeInSubProcess(); if (parent != null) { //目前进入到子流程中 parent.elementbox.attr({"stroke": "#000000", "stroke-width": 0.5}); } //无论是否有父元素,都需要进入这个方法 this.addParent(parent); }, setText: function (wenbenid) { //得到文本框的值,重新赋值给text //Raphaël\nkicks\nbutt! var tvalue = $(".taskinput input").val(); var temp = tvalue; if ($.trim(tvalue) != "" && wenbenid == this.id) { this.text.attr({"text": temp}); $(".taskinput input").val("");//清空 } }, unSelect: function () {//非选中状态 //小菜单回归原位 $(".right").css({"left": -100, "top": -100}); //外框隐藏 this.elementbox.attr({"stroke": "#000000", "stroke-width": 0.5}).hide(); this.ccelement.hide(); //文本框 if (this.selected == true) { var wenbenid = $(".taskinput input").attr("wenbenid"); if (wenbenid) { this.setText(wenbenid); } this.text.show(); } //文本框回归原位 $(".taskinput").css({"left": -100, "top": -100}); //中心线隐藏 this.centerLineX.hide(); this.centerLineY.hide(); this.selected = false; //完成情况的显示 if (this.completeState != 0) { var name = "divshow_" + this.id; $("#" + name).hide(); } }, removeElement: function () {//end圆删除元素 this.element.remove(); this.centerLineX.remove(); this.centerLineY.remove(); this.elementbox.remove(); this.ccelement.remove(); this.text.remove(); //文本框回归 $(".taskinput").css({"left": -100, "top": -100}); //小菜单回归原位 $(".right").css({"left": -100, "top": -100}); //父元素 if (this.parentElem) { this.parentElem.removeSubElement(this); this.parentElem = null; } //移除相关的线 var tempinlines = []; $.each(this.linein, function (index, line) { tempinlines.push(line); }); $.each(tempinlines, function (index, line) { line && line.removeElement(); }); }, removeInLine: function (line) { var _that = this; $.each(this.linein, function (index, elem) { if (elem && elem.id == line.id) { _that.linein.splice(index, 1); } }) }, comeInSubProcess: function () { //判断是否在子流程里面 var parent = this.flow.collisionSubProcess(this.coordinate[0], this.coordinate[1], this.coordinate[2], this.coordinate[3]); //被碰撞 return parent; }, comeInSubProcess2: function (L, R, T, B) {//判断是否在子流程里面 var parent = this.flow.collisionSubProcess(L, R, T, B); //被碰撞 return parent; }, addParent: function (parent) {//在子流程里的处理 //判断落点是否在子流程内,如果落在子流程内,则需要修改parentElem if (!parent) { parent = this.flow.collisionSubProcess(this.coordinate[0], this.coordinate[1], this.coordinate[2], this.coordinate[3]); //被碰撞 } if (parent != null) { var ids = []; $.each(parent.subElement, function (index, elem) { ids.push(elem.id); }) if ($.inArray(this.id, ids) == -1) { this.parentElem = parent; parent.subElement.push(this); //表示新加入的到某个节点上,则原来的所有的线段需要移除 //移除相关的线 this.removeLine(); //节点置前 //this.element.toFront(); this.elementbox.toFront(); } } else {//没有父元素 if (this.parentElem) { this.parentElem.removeSubElement(this); this.parentElem = null; //表示新加入的到其他的,则原来子流程中的所有的线段需要移除 this.removeLine(); } } //return parent; }, getText: function () { return this.text.attr("text"); }, removeLine: function () { //删除线段 var tempinlines = []; $.each(this.linein, function (index, line) { if (!line.self) { tempinlines.push(line); } }); $.each(tempinlines, function (index, line) { line && line.removeElement(); if (line) { delete this.flow.alllines[line.id]; //删除线元素 } }); } }); //转数字判断 function floatToFix4(num) { return parseFloat(num).toFixed(4); } //线上的圆点移动 lineintance是Line的实例, function _lineCircleMove(tx, ty, x, y, e, lineintance, circlecx, circlecy, circle, circlepxindex) { //console.log(tx,ty,x,y,e); lineintance.linepointsxy[circlepxindex][1] = circlecx + tx; lineintance.linepointsxy[circlepxindex][2] = circlecy + ty; //重写线段 lineintance.linestr = lineintance.combPath(); //lineintance.linestr="M"+lineintance.x1+","+lineintance.y1+"L"+(circlecx+tx)+","+(circlecy+ty)+"L"+lineintance.x2+","+lineintance.y2; lineintance.line.attr("path", lineintance.linestr); //lineintance.paper.circle(lineintance.bbox.cx+tx,lineintance.bbox.cy+ty,"3").attr("fill","#ff00ff"); circle.attr({"cx": circlecx + tx, "cy": circlecy + ty}); } function _lineCircleStart(x, y, e, lineintance, circlecx, circlecy) { return lineintance.currentPointInPathIndex(circlecx, circlecy); } function _lineCircleEnd(e, lineintance) { lineintance.bbox = lineintance.line.getBBox(); lineintance.linebox.attr({ "x": lineintance.bbox.x, "y": lineintance.bbox.y, "width": lineintance.bbox.width, "height": lineintance.bbox.height }); lineintance.linepointsxy = Raphael.parsePathString(lineintance.linestr); } function Gateway(flow, options) { this.flow = flow; //FlowDesigner类的实例 this.paper = flow.paper; //画布rapheal this.options = options; this.type = "gateway"; this.selected = false; this.id = options.id ? options.id : ""; this.isLoad = options.isLoad ? true : false; //是否是加载的元素 this.detail = options.detail; this.parentElem = null; //所属父级 this.parentElemStr = options.parentElem; //加载时所属父级的名称 this.element = null; //path 正菱形 this.img = null; this.elementbox = null; //扩大外框 this.bbox = null; //外框 this.coordinate = []; //当前元素的四条边坐标 this.fourpoint = []; //四个元素顶点坐标 this.centerLineCoordinate = []; //圆元素的上下左右四条边坐标,为显示中心线,小一点 this.centerMargin = 10; //向中心点向外4个方向扩展的距离 //元素 this.cx = options.cx; //中心点坐标x this.cy = options.cy;//中心点坐标y this.r = options.r; //正菱形中心点到其他4个点的垂直距离 this.bmargin = 4; //外框和元素的边距 this.centerLineX = null; this.centerLineY = null; this.ccelement = null; //圆心 this.centerpoint = []; //矩形的中心点 this.linein = []; //所有进来的线 this.lineout = [];//所有出去的线 this.text = null; //文本 this.content = {}; //网关内容 this.completeState = options.completeState || 0; //0 代表否 1代表已完 2代表正当 3代表还未开始 } Gateway.prototype = $.extend(Gateway.prototype, { init: function () { var number = this.flow.createGatewayNum(); var tempName = (new Date()).getTime(); //根据中心点和垂直半径得到四个顶点 //左上右下 this.fourpoint = [{"x": this.cx - this.r, "y": this.cy}, { "x": this.cx, "y": this.cy - this.r }, {"x": this.cx + this.r, "y": this.cy}, {"x": this.cx, "y": this.cy + this.r}]; //var c = paper.path("M10 10L90 90"); var str = "M" + this.fourpoint[0].x + "," + this.fourpoint[0].y + "L" + this.fourpoint[1].x + "," + this.fourpoint[1].y + "L" + this.fourpoint[2].x + "," + this.fourpoint[2].y + "L" + this.fourpoint[3].x + "," + this.fourpoint[3].y + "Z"; //菱形元素 switch (this.completeState) { case 1: //蓝色 this.element = this.paper.path(str).attr({ "fill": "#e0e9fe", "cursor": "pointer", "stroke": "#2632aa", "stroke-width": 1 }); break; case 2://绿色 this.element = this.paper.path(str).attr({ "fill": "#ebf8eb", "cursor": "pointer", "stroke": "#017501", "stroke-width": 1 }); break; case 3://灰色 this.element = this.paper.path(str).attr({ "fill": "#dadada", "cursor": "pointer", "stroke": "#acacac", "stroke-width": 1 }); break; default: this.element = this.paper.path(str).attr({ "cursor": "pointer", "fill": "#ffffff", "stroke": "#585858", "stroke-width": 1 }); break; } //正菱形 switch (this.detail) { case "exclusiveGateway": //this.img=this.paper.image("/flowmodify/images/exclusive_bg.png", this.cx-9, this.cy-9, 18, 18); if (this.completeState == 0) { this.img = this.paper.image(GatewayImgs.exclusiveGateway, this.cx - 9, this.cy - 9, 18, 18).attr({"cursor": "pointer"}); } else if (this.completeState == 1) { //蓝色 this.img = this.paper.image(GatewayImgsBlue.exclusiveGateway, this.cx - 9, this.cy - 9, 18, 18).attr({"cursor": "pointer"}); } else if (this.completeState == 2) {//绿色 this.img = this.paper.image(GatewayImgsGreen.exclusiveGateway, this.cx - 9, this.cy - 9, 18, 18).attr({"cursor": "pointer"}); } else if (this.completeState == 3) {//灰色 this.img = this.paper.image(GatewayImgsGray.exclusiveGateway, this.cx - 9, this.cy - 9, 18, 18).attr({"cursor": "pointer"}); } if (!this.isLoad) { this.id = "exclusiveGateway_" + tempName; } break; case "parallelGateway": if (this.completeState == 0) { this.img = this.paper.image(GatewayImgs.parallelGateway, this.cx - 10, this.cy - 10, 20, 20).attr({"cursor": "pointer"}); } else if (this.completeState == 1) {//蓝色 this.img = this.paper.image(GatewayImgsBlue.parallelGateway, this.cx - 10, this.cy - 10, 20, 20).attr({"cursor": "pointer"}); } else if (this.completeState == 2) {//绿色 this.img = this.paper.image(GatewayImgsGreen.parallelGateway, this.cx - 10, this.cy - 10, 20, 20).attr({"cursor": "pointer"}); } else if (this.completeState == 3) {//灰色 this.img = this.paper.image(GatewayImgsGray.parallelGateway, this.cx - 10, this.cy - 10, 20, 20).attr({"cursor": "pointer"}); } if (!this.isLoad) { this.id = "parallelGateway_" + tempName; } break; case "inclusiveGateway": if (this.completeState == 0) { this.img = this.paper.image(GatewayImgs.inclusiveGateway, this.cx - 11, this.cy - 11, 22, 22).attr({"cursor": "pointer"}); } else if (this.completeState == 1) {//蓝色 this.img = this.paper.image(GatewayImgsBlue.inclusiveGateway, this.cx - 11, this.cy - 11, 22, 22).attr({"cursor": "pointer"}); } else if (this.completeState == 2) {//绿色 this.img = this.paper.image(GatewayImgsGreen.inclusiveGateway, this.cx - 11, this.cy - 11, 22, 22).attr({"cursor": "pointer"}); } else if (this.completeState == 3) {//灰色 this.img = this.paper.image(GatewayImgsGray.inclusiveGateway, this.cx - 11, this.cy - 11, 22, 22).attr({"cursor": "pointer"}); } if (!this.isLoad) { this.id = "inclusiveGateway_" + tempName; } break; } //外框 this.bbox = this.element.getBBox(); //console.log(this.bbox); //扩大外框 this.elementbox = this.paper.rect(this.bbox.x - this.bmargin, this.bbox.y - this.bmargin, this.bbox.width + this.bmargin * 2, this.bbox.height + this.bmargin * 2).attr({ "stroke-dasharray": "- ", stroke: "#000000", "stroke-width": 0.5, "fill": "#ff0000", "fill-opacity": 0 }); //坐标(L,R,T,B) this.coordinate.push(this.bbox.x, this.bbox.x + this.bbox.width, this.bbox.y, this.bbox.y + this.bbox.height); //中心点坐标 this.centerpoint = [this.bbox.x + this.bbox.width / 2, this.bbox.y + this.bbox.height / 2]; //中心点向外扩展centerMargin=10,得到4条边,坐标(L,R,T,B) this.centerLineCoordinate.push(this.centerpoint[0] - this.centerMargin, this.centerpoint[0] + this.centerMargin, this.centerpoint[1] - this.centerMargin, this.centerpoint[1] + this.centerMargin); //文字 if (!this.isLoad) { this.text = this.paper.text(this.centerpoint[0], this.centerpoint[1] + this.r + 12, "网关" + number).attr({"font-size": "12px"}); } else { this.text = this.paper.text(this.centerpoint[0], this.centerpoint[1] + this.r + 12, this.options.text).attr({"font-size": "12px"}); } //隐藏的中心竖线 this.centerLineY = this.paper.path("M" + this.centerpoint[0] + ",0L" + this.centerpoint[0] + "," + this.flow._DEFALUTS_.height).attr({ "stroke-width": 2, "stroke": "#c1c1c1", "stroke-dasharray": "- " }).hide(); //隐藏的中心横线 this.centerLineX = this.paper.path("M0," + this.centerpoint[1] + "L" + this.flow._DEFALUTS_.width + "," + this.centerpoint[1]).attr({ "stroke-width": 2, "stroke": "#c1c1c1", "stroke-dasharray": "- " }).hide(); this.ccelement = this.paper.circle(this.centerpoint[0], this.centerpoint[1], 2).attr({ "fill": "#ff0000", "stroke": "ff0000" }).hide(); //圆心 //添加父元素 if (!this.isLoad) { this.addParent(); } var _that = this; if (this.completeState == 0) { //菱形的外框点击 this.elementbox.click(function (e) { if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { //小菜单 $(".right").css({ "left": _that.cx + _that.r + 10 - _that.flow.getScrollx(), "top": _that.cy - _that.r + _that.flow._DEFALUTS_.dy - _that.flow.getScrolly() }).attr("tempid", _that.id).end().find(".sequence").attr("tempid", _that.id).show(); _that.selected = true; //选中元素 var wenbenid = $(".taskinput input").attr("wenbenid"); if (wenbenid) { _that.setText(wenbenid); } _that.text.show(); } }); //菱形的外框双击 this.elementbox.dblclick(function (e) { if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { var tvalue = _that.text.attr("text"); $(".taskinput input").val(tvalue); $(".taskinput input").attr("wenbenid", _that.id); //显示文本框,-10任意调整的,为了显示在中间 $(".taskinput").css({ "left": _that.cx - _that.r - 10 - _that.flow.getScrollx(), "top": (_that.cy - 10 + _that.flow._DEFALUTS_.dy - _that.flow.getScrolly()), "width": 60 }); _that.selected = true; //文本框本身隐藏 _that.text.hide(); } }); //菱形的单击 this.element.click(function (e) { if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { _that.elementbox.show(); $(".right").css({ "left": _that.cx + _that.r + 10 - _that.flow.getScrollx(), "top": _that.cy - _that.r + _that.flow._DEFALUTS_.dy - _that.flow.getScrolly() }).attr("tempid", _that.id).end().find(".sequence").attr("tempid", _that.id).show(); } }); //菱形中图片的单击 this.img.click(function (e) { if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { _that.elementbox.show(); $(".right").css({ "left": _that.cx + _that.r + 10 - _that.flow.getScrollx(), "top": _that.cy - _that.r + _that.flow._DEFALUTS_.dy - _that.flow.getScrolly() }).attr("tempid", _that.id).end().find(".sequence").attr("tempid", _that.id).show(); } }); //网关节点的外层框拖动 var weiyiX = 0; var weiyiY = 0; var dropStatus = false; var startX = 0; var startY = 0; var bpz = null; var bpzcenter = null; var startpointx = 0; var startpointy = 0; this.elementbox.drag(function (tx, ty, x, y, e) { //move中 if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { dropStatus = true; //限制去菜单那块 if (e.clientX < (134 + _that.flow._DEFALUTS_.dx + weiyiX)) { e.clientX = 134 + _that.flow._DEFALUTS_.dx; dropStatus = false; return; } //限制画布最右侧边界 if (e.clientX > _that.flow._DEFALUTS_.width - (_that.r + _that.bmargin) * 2 + _that.flow._DEFALUTS_.dx + weiyiX) { dropStatus = false; return; } //限制头部 if (e.clientY < (0 + _that.flow._DEFALUTS_.dy + weiyiY)) { e.clientY = 0 + _that.flow._DEFALUTS_.dy; dropStatus = false; return; } //限制画布底部边界 if (e.clientY > (0 + _that.flow._DEFALUTS_.height - (_that.r + _that.bmargin) * 2 + _that.flow._DEFALUTS_.dy + weiyiY)) { dropStatus = false; return; } this.attr({ "x": e.clientX - _that.flow._DEFALUTS_.dx - weiyiX, "y": e.clientY - _that.flow._DEFALUTS_.dy - weiyiY }); //碰撞检测 var L = e.clientX - _that.flow._DEFALUTS_.dx - weiyiX; var R = L + _that.r * 2; var T = e.clientY - _that.flow._DEFALUTS_.dy - weiyiY; var B = T + _that.r * 2; bpz = _that.flow.collision(_that, L, R, T, B); //被碰撞 if (bpz != null && bpz.type != "subProcess") { dropStatus = false; } bpzcenter = _that.flow.collisionCenterLine(_that, L, R, T, B); //中心线匹配 } }, function (x, y, e) { //move开始 weiyiX = e.clientX - _that.flow._DEFALUTS_.dx - _that.bbox.x + _that.bmargin; //offsetX,不需要减1 weiyiY = e.clientY - _that.flow._DEFALUTS_.dy - _that.bbox.y + _that.bmargin; //offsetY,不需要减32 startX = _that.bbox.x - _that.bmargin; startY = _that.bbox.y - _that.bmargin; startpointx = e.clientX; startpointy = e.clientY; }, function (e) {//move结束 var endpointx = e.clientX; var endpointy = e.clientY; if (Math.abs(endpointx - startpointx) < 2 && Math.abs(endpointy - startpointy) < 2) {//阻止点击就移动 dropStatus = false; } if (dropStatus == true) { var elemnetboxbbox = this.getBBox(); //判断是否进入子流程 if (bpz && bpz.type == "subProcess") { //说明进入在子流程中 if (_that.parentElem == null || _that.parentElem.id != bpz.id) { //表示新的入到一个子流程中 if (_that.linein.length > 0 || _that.lineout.length > 0) { //如果含有线段,则必须提示,因为进入新的空间,旧的空间中的线段需要删除 $.messager.confirm('再次确认', '该网关节点进入子流程会删除原来的线段,还要继续进入吗?', function (r) { if (!r) { _that.elementbox.attr({"x": startX, "y": startY}); //不能落下的地方就返回 } else { _that.render(elemnetboxbbox.cx, elemnetboxbbox.cy, bpzcenter); } }) } else { //没有线段 _that.render(elemnetboxbbox.cx, elemnetboxbbox.cy, bpzcenter); } } } else if (bpz == null) { if (_that.parentElem != null) { //原来在小空间中 if (_that.linein.length > 0 || _that.lineout.length > 0) { //如果含有线段,则必须提示,因为进入新的空间,旧的空间中的线段需要删除 var L = elemnetboxbbox.x; var R = L + _that.r * 2; var T = elemnetboxbbox.y; var B = T + _that.r * 2; //判断当前是否已经出了小空间 if (!_that.comeInSubProcess2(L, R, T, B)) { $.messager.confirm('再次确认', '该网关节点原属于子流程空间,进入父空间时会删除原来的线段,还要继续进入吗?', function (r) { if (!r) { _that.elementbox.attr({"x": startX, "y": startY}); //不能落下的地方就返回 } else { _that.render(elemnetboxbbox.cx, elemnetboxbbox.cy, bpzcenter); } }) } else { //没有出小空间 _that.render(elemnetboxbbox.cx, elemnetboxbbox.cy, bpzcenter); } } else { //没有线段 _that.render(elemnetboxbbox.cx, elemnetboxbbox.cy, bpzcenter); } } else { //原来在大空间中 _that.render(elemnetboxbbox.cx, elemnetboxbbox.cy, bpzcenter); } } } else { this.attr({"x": startX, "y": startY}); //不能落下的地方就返回 } dropStatus = false; return false; }); } }, render: function (cx, cy, bpzcenter) { //网关的渲染 if (bpzcenter != null) { if (bpzcenter[0] != null && bpzcenter[1] == null) { //y轴吸附,x轴不吸附 if (bpzcenter[0].type == "start" || bpzcenter[0].type == "end" || bpzcenter[0].type == "gateway") { cx = bpzcenter[0].cx; } else if (bpzcenter[0].type == "userTask" || bpzcenter[0].type == "subProcess") { cx = bpzcenter[0].x + bpzcenter[0].w / 2; //因为2个元素的大小不一定相同,先到中心点,再减去自身的一半 } } else if (bpzcenter[0] == null && bpzcenter[1] != null) { //x轴吸附,y轴不吸附 if (bpzcenter[1].type == "start" || bpzcenter[1].type == "end" || bpzcenter[1].type == "gateway") { cy = bpzcenter[1].cy; } else if (bpzcenter[1].type == "userTask" || bpzcenter[1].type == "subProcess") { cy = bpzcenter[1].y + bpzcenter[1].h / 2; //因为2个元素的大小不一定相同,先到中心点,再减去自身的一半 } } else if (bpzcenter[0] != null && bpzcenter[1] != null) { //y轴吸附,x轴吸附 if (bpzcenter[0].type == "start" || bpzcenter[0].type == "end" || bpzcenter[0].type == "gateway") { cx = bpzcenter[0].cx; } else if (bpzcenter[0].type == "userTask" || bpzcenter[0].type == "subProcess") { cx = bpzcenter[0].x + bpzcenter[0].w / 2; //因为2个元素的大小不一定相同,先到中心点,再减去自身的一半 } if (bpzcenter[1].type == "start" || bpzcenter[1].type == "end" || bpzcenter[1].type == "gateway") { cy = bpzcenter[1].cy; } else if (bpzcenter[1].type == "userTask" || bpzcenter[1].type == "subProcess") { cy = bpzcenter[1].y + bpzcenter[1].h / 2; //因为2个元素的大小不一定相同,先到中心点,再减去自身的一半 } } } // this.cx = x + this.r; // this.cy = y + this.r; this.cx = cx; this.cy = cy; this.fourpoint = [{"x": this.cx - this.r, "y": this.cy}, { "x": this.cx, "y": this.cy - this.r }, {"x": this.cx + this.r, "y": this.cy}, {"x": this.cx, "y": this.cy + this.r}]; //var c = paper.path("M10 10L90 90"); var str = "M" + this.fourpoint[0].x + "," + this.fourpoint[0].y + "L" + this.fourpoint[1].x + "," + this.fourpoint[1].y + "L" + this.fourpoint[2].x + "," + this.fourpoint[2].y + "L" + this.fourpoint[3].x + "," + this.fourpoint[3].y + "Z"; this.element.attr("path", str); switch (this.detail) { case "exclusiveGateway": this.img.attr({"x": this.cx - 9, "y": this.cy - 9}); break; case "parallelGateway": this.img.attr({"x": this.cx - 10, "y": this.cy - 10}); break; case "inclusiveGateway": this.img.attr({"x": this.cx - 11, "y": this.cy - 11}); break; } this.bbox = this.element.getBBox(); //扩大的外框 this.elementbox.attr({"x": this.bbox.x - this.bmargin, "y": this.bbox.y - this.bmargin}); //修改坐标(L,R,T,B) this.coordinate[0] = this.bbox.x; this.coordinate[1] = this.bbox.x + this.bbox.width; this.coordinate[2] = this.bbox.y; this.coordinate[3] = this.bbox.y + this.bbox.height; //中心点坐标 this.centerpoint = [this.cx, this.cy]; //中心点向外扩展centerMargin=10,得到4条边,坐标(L,R,T,B) this.centerLineCoordinate = []; this.centerLineCoordinate.push(this.centerpoint[0] - this.centerMargin, this.centerpoint[0] + this.centerMargin, this.centerpoint[1] - this.centerMargin, this.centerpoint[1] + this.centerMargin); //文字 this.text.attr({"x": this.centerpoint[0], "y": this.centerpoint[1] + this.r + 12}); //移动隐藏的中心竖线 this.centerLineY.attr("path", "M" + this.centerpoint[0] + ",0L" + this.centerpoint[0] + "," + this.flow._DEFALUTS_.height); //移动隐藏的中心横线 this.centerLineX.attr("path", "M0," + this.centerpoint[1] + "L" + this.flow._DEFALUTS_.width + "," + this.centerpoint[1]); this.ccelement.attr({"cx": this.centerpoint[0], "cy": this.centerpoint[1]}); //父元素处理 var parent = this.comeInSubProcess(); if (parent != null) { //目前进入到子流程中 parent.elementbox.attr({"stroke": "#000000", "stroke-width": 0.5}); } //无论是否有父元素,都需要进入这个方法 this.addParent(parent); var _that = this; //所有出去的点,因为坐标变了,需要重绘 $.each(this.lineout, function (index, lineElem) { lineElem.redrawStart(_that.cx, _that.cy); }); //所有进入的点,因为坐标变了,需要重绘 $.each(this.linein, function (index, lineElem) { //得到点 lineElem.redrawEnd(_that.cx, _that.cy); }); }, setText: function (wenbenid) { //得到文本框的值,重新赋值给text //Raphaël\nkicks\nbutt! var tvalue = $(".taskinput input").val(); var temp = tvalue; if ($.trim(tvalue) != "" && wenbenid == this.id) { this.text.attr({"text": temp}); $(".taskinput input").val("");//清空 } }, unSelect: function () { //gateway的unSelect //小菜单回归原位 $(".right").css({"left": -100, "top": -100}); //外框隐藏 this.elementbox.attr({"stroke": "#000000", "stroke-width": 0.5}).hide(); //圆心 this.ccelement.hide(); //文本框 if (this.selected == true) { var wenbenid = $(".taskinput input").attr("wenbenid"); if (wenbenid) { this.setText(wenbenid); } this.text.show(); } //文本框回归原位 $(".taskinput").css({"left": -100, "top": -100}); //中心线隐藏 this.centerLineX.hide(); this.centerLineY.hide(); this.selected = false; //完成情况的显示 if (this.completeState != 0) { var name = "divshow_" + this.id; $("#" + name).hide(); } }, removeElement: function () { this.element.remove(); this.centerLineX.remove(); this.centerLineY.remove(); this.elementbox.remove(); this.img.remove(); this.ccelement.remove(); this.text.remove(); //文本框回归 $(".taskinput").css({"left": -100, "top": -100}); //小菜单回归原位 $(".right").css({"left": -100, "top": -100}); //删除父元素中对本元素的调用 if (this.parentElem) { this.parentElem.removeSubElement(this); this.parentElem = null; } //移除相关的线 var tempoutlines = []; $.each(this.lineout, function (index, line) { tempoutlines.push(line); }); $.each(tempoutlines, function (index, line) { line && line.removeElement(); }); var tempinlines = []; $.each(this.linein, function (index, line) { tempinlines.push(line); }); $.each(tempinlines, function (index, line) { line && line.removeElement(); }); }, removeOutLine: function (line) { var _that = this; $.each(this.lineout, function (index, elem) { if (elem && elem.id == line.id) { _that.lineout.splice(index, 1); } }) }, removeInLine: function (line) { var _that = this; $.each(this.linein, function (index, elem) { if (elem && elem.id == line.id) { _that.linein.splice(index, 1); } }) }, comeInSubProcess: function () { //判断是否在子流程里面 var parent = this.flow.collisionSubProcess(this.coordinate[0], this.coordinate[1], this.coordinate[2], this.coordinate[3]); //被碰撞 return parent; }, comeInSubProcess2: function (L, R, T, B) {//判断是否在子流程里面 console.log(L, R, T, B) var parent = this.flow.collisionSubProcess(L, R, T, B); //被碰撞 return parent; }, addParent: function (parent) {//在子流程里的处理 //判断落点是否在子流程内,如果落在子流程内,则需要修改parentElem if (!parent) { parent = this.flow.collisionSubProcess(this.coordinate[0], this.coordinate[1], this.coordinate[2], this.coordinate[3]); //被碰撞 } if (parent != null) { var ids = []; $.each(parent.subElement, function (index, elem) { ids.push(elem.id); }) if ($.inArray(this.id, ids) == -1) { this.parentElem = parent; parent.subElement.push(this); //表示新加入的到某个节点上,则原来的所有的线段需要移除 //移除相关的线 this.removeLine(); //节点置前 //this.element.toFront(); this.elementbox.toFront(); } } else {//没有父元素 if (this.parentElem) { this.parentElem.removeSubElement(this); this.parentElem = null; //表示新加入的到其他的,则原来子流程中的所有的线段需要移除 this.removeLine(); } } //return parent; }, getText: function () { return this.text.attr("text"); }, removeLine: function () { //删除线段 var tempoutlines = []; $.each(this.lineout, function (index, line) { if (!line.self) { tempoutlines.push(line); } }); $.each(tempoutlines, function (index, line) { line && line.removeElement(); if (line) { delete this.flow.alllines[line.id]; //删除线元素 } }); var tempinlines = []; $.each(this.linein, function (index, line) { if (!line.self) { tempinlines.push(line); } }); $.each(tempinlines, function (index, line) { line && line.removeElement(); if (line) { delete this.flow.alllines[line.id]; //删除线元素 } }); } }); //子流程 function SubProcess(flow, options) { this.flow = flow; //FlowDesigner类的实例 this.paper = flow.paper; //画布rapheal this.options = options; this.type = "subProcess"; this.selected = false; this.id = options.id ? options.id : ""; this.isLoad = options.isLoad ? true : false; //是否是加载的元素 this.parentElem = null; //所属父级 //this.parentElemStr=options.parentElem; //加载时所属父级的名称 this.element = null; //任务方块 this.elementbox = null; //扩大外框 this.bbox = null; //外框 this.coordinate = []; //当前元素的上下左右坐标 this.fourpoint = []; //四个元素顶点坐标 this.centerLineCoordinate = []; //圆元素的上下左右四条边坐标,为显示中心线,小一点 this.centerMargin = 10; //向中心点向外4个方向扩展的距离 this.centerLineY = null; this.centerLineX = null; //控制点 this.$elementctrl1 = null; this.$elementctrl4 = null; //元素 this.x = options.x; //顶点坐标x this.y = options.y;//顶点坐标y this.w = options.w;//宽 this.h = options.h;//高 this.angle = 4; //弧度 this.bmargin = 4; //外框和元素的边距 this.ccelement = null; //圆心 this.centerpoint = []; //矩形的中心点 this.linein = []; //所有进来的线 this.lineout = [];//所有出去的线 this.subElement = [];//所有子元素 this.content = {}; //子流程内容 this.completeState = options.completeState || 0; //0 代表否 1代表已完 2代表正当 3代表还未开始 } SubProcess.prototype = $.extend(SubProcess.prototype, { init: function () { var number = this.flow.createSubprocessNum(); var tempName = (new Date()).getTime(); if (!this.isLoad) { this.id = "subProcess_" + tempName; } //矩形框 switch (this.completeState) { case 1://蓝色 this.element = this.paper.rect(this.x, this.y, this.w, this.h, this.angle).attr({ "fill": "#e0e9fe", "cursor": "pointer", "stroke": "#2632aa" }).toBack(); break; case 2://绿色 this.element = this.paper.rect(this.x, this.y, this.w, this.h, this.angle).attr({ "fill": "#ebf8eb", "cursor": "pointer", "stroke": "#017501" }).toBack(); break; case 3://灰色 this.element = this.paper.rect(this.x, this.y, this.w, this.h, this.angle).attr({ "fill": "#dadada", "cursor": "pointer", "stroke": "#acacac" }).toBack(); break; default: this.element = this.paper.rect(this.x, this.y, this.w, this.h, this.angle).attr({ "fill": "#ffffff", "fill-opacity": 0, "cursor": "pointer" }).toBack(); break; } //外框 this.bbox = this.element.getBBox(); //扩大外框 this.elementbox = this.paper.rect(this.bbox.x - this.bmargin, this.bbox.y - this.bmargin, this.bbox.width + this.bmargin * 2, this.bbox.height + this.bmargin * 2, false).attr({ "stroke-dasharray": "- ", stroke: "#000000", "stroke-width": 0.5, "fill": "#ff0000", "fill-opacity": 0 }); //坐标(L,R,T,B) this.coordinate.push(this.bbox.x, this.bbox.x + this.bbox.width, this.bbox.y, this.bbox.y + this.bbox.height); //根据中心点和宽度得到四个顶点 //定点开始顺时针 this.fourpoint = [{"x": this.x, "y": this.y}, {"x": this.x + this.w, "y": this.y}, { "x": this.x + this.w, "y": this.y + this.h }, {"x": this.x, "y": this.y + this.h}]; //文字 if (!this.isLoad) { this.text = this.paper.text(this.bbox.x + this.bbox.width / 2, this.bbox.y + 14, "子流程" + number).attr({"font-size": "14px"}); } else { this.text = this.paper.text(this.bbox.x + this.bbox.width / 2, this.bbox.y + 14, this.options.text).attr({"font-size": "14px"}); } //控制点,-10.+8就是想放在框外边 this.$elementctrl1 = $("
"); $("#" + this.flow._DEFALUTS_.id).append(this.$elementctrl1); this.$elementctrl4 = $("
"); $("#" + this.flow._DEFALUTS_.id).append(this.$elementctrl4); //中心点坐标 this.centerpoint = [this.bbox.x + this.bbox.width / 2, this.bbox.y + this.bbox.height / 2]; //中心点向外扩展centerMargin=10,得到4条边,坐标(L,R,T,B) this.centerLineCoordinate.push(this.centerpoint[0] - this.centerMargin, this.centerpoint[0] + this.centerMargin, this.centerpoint[1] - this.centerMargin, this.centerpoint[1] + this.centerMargin); //隐藏的中心竖线 this.centerLineY = this.paper.path("M" + this.centerpoint[0] + ",0L" + this.centerpoint[0] + "," + this.flow._DEFALUTS_.height).attr({ "stroke-width": 2, "stroke": "#c1c1c1", "stroke-dasharray": "- " }).hide(); //隐藏的中心横线 this.centerLineX = this.paper.path("M0," + this.centerpoint[1] + "L" + this.flow._DEFALUTS_.width + "," + this.centerpoint[1]).attr({ "stroke-width": 2, "stroke": "#c1c1c1", "stroke-dasharray": "- " }).hide(); this.ccelement = this.paper.circle(this.centerpoint[0], this.centerpoint[1], 2).attr({ "fill": "#ff0000", "stroke": "ff0000" }).hide(); //圆心 var _that = this; if (this.completeState == 0) { //子流程的外框点击 this.elementbox.click(function (e) { if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { //小菜单 $(".right").css({ "left": _that.x + _that.w + 10 - _that.flow.getScrollx(), "top": _that.y + _that.flow._DEFALUTS_.dy - _that.flow.getScrolly() }).attr("tempid", _that.id).end().find(".sequence").attr("tempid", _that.id).show(); //隐藏控制点 _that.$elementctrl1.hide(); _that.$elementctrl4.hide(); _that.selected = true; //选中元素 _that.elementbox.show(); var wenbenid = $(".taskinput input").attr("wenbenid"); if (wenbenid) { _that.setText(wenbenid); } _that.text.show(); } }); //子流程的外框双击 this.elementbox.dblclick(function (e) { if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { var tvalue = _that.text.attr("text"); $(".taskinput input").val(tvalue); $(".taskinput input").attr("wenbenid", _that.id); //显示文本框 $(".taskinput").css({ "left": _that.x - _that.flow.getScrollx(), "top": (_that.y + 2 + _that.flow._DEFALUTS_.dy - _that.flow.getScrolly()), "width": _that.w }); _that.selected = true; //文本框本身隐藏 _that.text.hide(); } }); //子流程的单击 this.element.click(function (e) { if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { _that.elementbox.show(); $(".right").css({ "left": _that.x + _that.w + 10 - _that.flow.getScrollx(), "top": _that.y + _that.flow._DEFALUTS_.dy - _that.flow.getScrolly() }).attr("tempid", _that.id).end().find(".sequence").attr("tempid", _that.id).show(); //显示控制点 _that.$elementctrl1.show(); _that.$elementctrl4.show(); } }); //子流程节点的外层框拖动 var weiyiX = 0; var weiyiY = 0; var dropStatus = false; var startX = 0; var startY = 0; var bpz = null; var bpzcenter = null; var startpointx = 0; var startpointy = 0; this.elementbox.drag(function (tx, ty, x, y, e) { //move中 if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { dropStatus = true; //限制去菜单那块 if (e.clientX < (134 + _that.flow._DEFALUTS_.dx + weiyiX)) { e.clientX = 134 + _that.flow._DEFALUTS_.dx; dropStatus = false; return; } //限制画布最右侧边界 if (e.clientX > _that.flow._DEFALUTS_.width - (_that.w + _that.bmargin * 2) + _that.flow._DEFALUTS_.dx + weiyiX) { dropStatus = false; return; } //限制头部 if (e.clientY < (0 + _that.flow._DEFALUTS_.dy + weiyiY)) { e.clientY = 0 + _that.flow._DEFALUTS_.dy; dropStatus = false; return; } //限制画布底部边界 if (e.clientY > (0 + _that.flow._DEFALUTS_.height - (_that.h + _that.bmargin * 2) + _that.flow._DEFALUTS_.dy + weiyiY)) { dropStatus = false; return; } this.attr({ "x": e.clientX - _that.flow._DEFALUTS_.dx - weiyiX, "y": e.clientY - _that.flow._DEFALUTS_.dy - weiyiY }); //碰撞检测 var L = e.clientX - _that.flow._DEFALUTS_.dx - weiyiX; var R = L + _that.w; var T = e.clientY - _that.flow._DEFALUTS_.dy - weiyiY; var B = T + _that.h; //console.log(_that.id, L, R, T, B); bpz = _that.flow.collision(_that, L, R, T, B); //被碰撞 if (bpz != null) { dropStatus = false; } bpzcenter = _that.flow.subProcessCollisionCenterLine(_that, L, R, T, B); //中心线匹配 } }, function (x, y, e) { //move开始 //文本框回归原位 $(".taskinput").css({"left": -100, "top": -100}); weiyiX = e.clientX - _that.flow._DEFALUTS_.dx - _that.bbox.x + _that.bmargin; //offsetX,不需要减1 weiyiY = e.clientY - _that.flow._DEFALUTS_.dy - _that.bbox.y + _that.bmargin; //offsetY,不需要减32 startX = _that.bbox.x - _that.bmargin; startY = _that.bbox.y - _that.bmargin; startpointx = e.clientX; startpointy = e.clientY; }, function (e) {//move结束 var endpointx = e.clientX; var endpointy = e.clientY; if (Math.abs(endpointx - startpointx) < 2 && Math.abs(endpointy - startpointy) < 2) {//阻止点击就移动 dropStatus = false; } if (dropStatus == true) { var x = e.clientX - _that.flow._DEFALUTS_.dx - weiyiX; var y = e.clientY - _that.flow._DEFALUTS_.dy - weiyiY; //本身渲染 var dxy = _that.render(x, y, bpzcenter); //子元素的移动 //var dx=endpointx - startpointx; //var dy=endpointy - startpointy; var dx = dxy.dx; var dy = dxy.dy; var lines = []; var linestrs = []; //收集线段,必须先收集线段,修改小圆点坐标,再收集节点。因为节点上需要修改起始和结束的位置,需要已经修改好的小圆点 $.each(_that.subElement, function (index, elem) { switch (elem.type) { case "end": $.each(elem.linein, function (index, line) { if ($.inArray(line.id, linestrs) == -1) { linestrs.push(line.id); lines.push(line); } }); break; case "start": $.each(elem.lineout, function (index, line) { if ($.inArray(line.id, linestrs) == -1) { linestrs.push(line.id); lines.push(line); } }); break; case "gateway": case "userTask": $.each(elem.linein, function (index, line) { if ($.inArray(line.id, linestrs) == -1) { linestrs.push(line.id); lines.push(line); } }); $.each(elem.lineout, function (index, line) { if ($.inArray(line.id, linestrs) == -1) { linestrs.push(line.id); lines.push(line); } }) break; } }) //修改线段上的小圆点坐标 //线上小圆点的渲染 $.each(lines, function (index, line) { $.each(line.linepoints, function (index, sc) { var circlepxindex = sc.belongLine.currentPointInPathIndex(sc.cx, sc.cy); var newcx = sc.cx + dx, newcy = sc.cy + dy; sc.render({"cx": newcx, "cy": newcy}); sc.belongLine.linepointsxy[circlepxindex][1] = newcx; sc.belongLine.linepointsxy[circlepxindex][2] = newcy; //重写线段 sc.belongLine.linestr = sc.belongLine.combPath(); sc.belongLine.line.attr("path", sc.belongLine.linestr); //修改text坐标 sc.belongLine.renderText(); }) }) //收集元素 $.each(_that.subElement, function (index, elem) { switch (elem.type) { case "end": case "gateway": case "start": var cx = elem.cx + dx, cy = elem.cy + dy; elem.render(cx, cy, null); break; case "userTask": var x = elem.x + dx, y = elem.y + dy; elem.render(x, y, null); break; } }); } else { this.attr({"x": startX, "y": startY}); //不能落下的地方就返回 } dropStatus = false; return false; }); //子流程的控制点4的移动 var ctrl4startx = 0; var ctrl4starty = 0; var ctrl4oldstartx = 0; var ctrl4oldstarty = 0; this.$elementctrl4.draggable({ cursor: "se-resize", revert: true, onStartDrag: function (e) { if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { ctrl4oldstartx = ctrl4startx = e.clientX; ctrl4oldstarty = ctrl4starty = e.clientY; } }, onDrag: function (e) { if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { var elementboxbox = _that.elementbox.getBBox(); var width = elementboxbox.width; var height = elementboxbox.height; var ctrl4dragpointx = e.clientX; var ctrl4dragpointy = e.clientY; width = width + ctrl4dragpointx - ctrl4startx; height = height + ctrl4dragpointy - ctrl4starty; _that.elementbox.attr({"width": width, "height": height}); ctrl4startx = ctrl4dragpointx; ctrl4starty = ctrl4dragpointy; } }, onStopDrag: function (e) { if (_that.flow.addPoint == false && _that.flow.subtractPoint == false) { var ctrl4endx = e.clientX; var ctrl4endy = e.clientY; var dwidth = ctrl4endx - ctrl4oldstartx; var dheight = ctrl4endy - ctrl4oldstarty; var elementWidth = _that.element.attr("width"); var elementHeight = _that.element.attr("height"); _that.element.attr({"width": elementWidth + dwidth, "height": elementHeight + dheight}); _that.w = elementWidth + dwidth; _that.h = elementHeight + dheight; _that.render(_that.bbox.x, _that.bbox.y, null); } } }) //子流程的控制点1的移动(移动的是left,top,width,height) var ctrl1startx = 0; var ctrl1starty = 0; var ctrl1oldstartx = 0; var ctrl1oldstarty = 0; var ctr1tx = 0; var ctr1ty = 0; this.$elementctrl1.draggable({ cursor: "nw-resize", revert: true, onStartDrag: function (e) { ctrl1oldstartx = ctrl1startx = e.clientX; ctrl1oldstarty = ctrl1starty = e.clientY; var oldleft = $(this).css("left"); var oldtop = $(this).css("top"); ctr1tx = e.clientX - parseFloat(oldleft); ctr1ty = e.clientY - parseFloat(oldtop); }, onDrag: function (e) { var elementboxbox = _that.elementbox.getBBox(); var width = elementboxbox.width; var height = elementboxbox.height; var ctrl1dragpointx = e.clientX; var ctrl1dragpointy = e.clientY; width = width - (ctrl1dragpointx - ctrl1startx); height = height - (ctrl1dragpointy - ctrl1starty); var ctr1left = e.clientX - ctr1tx - _that.flow._DEFALUTS_.dx + 10; var ctr1top = e.clientY - ctr1ty - _that.flow._DEFALUTS_.dy + 10; _that.elementbox.attr({"x": ctr1left, "y": ctr1top, "width": width, "height": height}); ctrl1startx = ctrl1dragpointx; ctrl1starty = ctrl1dragpointy; }, onStopDrag: function (e) { var ctrl1endx = e.clientX; var ctrl1endy = e.clientY; var x = ctrl1endx - ctr1tx - _that.flow._DEFALUTS_.dx + _that.bmargin + 10; var y = ctrl1endy - ctr1ty - _that.flow._DEFALUTS_.dy + _that.bmargin + 10; var dwidth = -(ctrl1endx - ctrl1oldstartx); var dheight = -(ctrl1endy - ctrl1oldstarty); var elementWidth = _that.element.attr("width"); var elementHeight = _that.element.attr("height"); //元素 _that.element.attr({ "x": x, "y": y, "width": elementWidth + dwidth, "height": elementHeight + dheight }); //属性 _that.x = x; _that.y = y; _that.w = elementWidth + dwidth; _that.h = elementHeight + dheight; _that.render(x, y, null); } }) } }, render: function (x, y, bpzcenter) { //子流程的渲染 if (bpzcenter != null) { if (bpzcenter[0] != null && bpzcenter[1] == null) { //y轴吸附,x轴不吸附 if (bpzcenter[0].type == "start" || bpzcenter[0].type == "end" || bpzcenter[0].type == "gateway") { x = bpzcenter[0].cx - this.w / 2; } else if (bpzcenter[0].type == "userTask" || bpzcenter[0].type == "subProcess") { x = bpzcenter[0].x + bpzcenter[0].w / 2 - this.w / 2; //因为2个元素的大小不一定相同,先到中心点,再减去自身的一半 } } else if (bpzcenter[0] == null && bpzcenter[1] != null) { //x轴吸附,y轴不吸附 if (bpzcenter[1].type == "start" || bpzcenter[1].type == "end" || bpzcenter[1].type == "gateway") { y = bpzcenter[1].cy - this.h / 2; } else if (bpzcenter[1].type == "userTask" || bpzcenter[1].type == "subProcess") { y = bpzcenter[1].y + bpzcenter[1].h / 2 - this.h / 2; //因为2个元素的大小不一定相同,先到中心点,再减去自身的一半 } } else if (bpzcenter[0] != null && bpzcenter[1] != null) { //y轴吸附,x轴吸附 if (bpzcenter[0].type == "start" || bpzcenter[0].type == "end" || bpzcenter[0].type == "gateway") { x = bpzcenter[0].cx - this.w / 2; } else if (bpzcenter[0].type == "userTask" || bpzcenter[0].type == "subProcess") { x = bpzcenter[0].x + bpzcenter[0].w / 2 - this.w / 2; //因为2个元素的大小不一定相同,先到中心点,再减去自身的一半 } if (bpzcenter[1].type == "start" || bpzcenter[1].type == "end" || bpzcenter[1].type == "gateway") { y = bpzcenter[1].cy - this.h / 2; } else if (bpzcenter[1].type == "userTask" || bpzcenter[1].type == "subProcess") { y = bpzcenter[1].y + bpzcenter[1].h / 2 - this.h / 2; //因为2个元素的大小不一定相同,先到中心点,再减去自身的一半 } } } var oldx = this.x; var oldy = this.y; this.x = x; this.y = y; this.element.attr({"x": x, "y": y}); this.bbox = this.element.getBBox(); this.text.attr({"x": this.bbox.x + this.bbox.width / 2, "y": this.bbox.y + 14}) //扩大的外框 this.elementbox.attr({"x": this.bbox.x - this.bmargin, "y": this.bbox.y - this.bmargin}); //修改坐标(L,R,T,B) this.coordinate[0] = this.bbox.x; this.coordinate[1] = this.bbox.x + this.bbox.width; this.coordinate[2] = this.bbox.y; this.coordinate[3] = this.bbox.y + this.bbox.height; //中心点坐标 this.centerpoint = [this.bbox.x + this.w / 2, this.bbox.y + this.h / 2]; //圆心 this.ccelement.attr({"cx": this.centerpoint[0], "cy": this.centerpoint[1]}); //根据中心点和宽度高度得到四个顶点 //定点开始顺时针 this.fourpoint = [{"x": this.x, "y": this.y}, {"x": this.x + this.w, "y": this.y}, { "x": this.x + this.w, "y": this.y + this.h }, {"x": this.x, "y": this.y + this.h}]; //中心点向外扩展centerMargin=10,得到4条边,坐标(L,R,T,B) this.centerLineCoordinate = []; this.centerLineCoordinate.push(this.centerpoint[0] - this.centerMargin, this.centerpoint[0] + this.centerMargin, this.centerpoint[1] - this.centerMargin, this.centerpoint[1] + this.centerMargin); //移动隐藏的中心竖线 this.centerLineY.attr("path", "M" + this.centerpoint[0] + ",0L" + this.centerpoint[0] + "," + this.flow._DEFALUTS_.height); //移动隐藏的中心横线 this.centerLineX.attr("path", "M0," + this.centerpoint[1] + "L" + this.flow._DEFALUTS_.width + "," + this.centerpoint[1]); //控制点 this.$elementctrl1.css({ "left": (this.bbox.x - this.bmargin - 10), "top": (this.bbox.y - this.bmargin - 10 + this.flow._DEFALUTS_.dy) }); this.$elementctrl4.css({ "left": (this.bbox.x - this.bmargin + this.bbox.width + 8), "top": (this.bbox.y - this.bmargin + this.bbox.height + 8 + this.flow._DEFALUTS_.dy) }); //所有出去的点,因为坐标变了,需要重绘 var _that = this; $.each(this.lineout, function (index, lineElem) { if (!lineElem.self) { //不是指向自身的点 lineElem.redrawStart(_that.bbox.cx, _that.bbox.cy); } else { //是指向自身的线,需要和节点一起变化,重绘 lineElem.renderMoveSelf(); } }); //所有进入的点,因为坐标变了,需要重绘 $.each(this.linein, function (index, lineElem) { //得到点 if (!lineElem.self) { lineElem.redrawEnd(_that.bbox.cx, _that.bbox.cy); } else { //是指向自身的线,需要和节点一起变化,重绘 lineElem.renderMoveSelf(); } }); return {"dx": x - oldx, "dy": y - oldy}; }, unSelect: function () {//非选中状态 //小菜单回归原位 $(".right").css({"left": -100, "top": -100}); if (this.selected == true) { var wenbenid = $(".taskinput input").attr("wenbenid"); if (wenbenid) { this.setText(wenbenid); } this.text.show(); } //文本框回归原位 $(".taskinput").css({"left": -100, "top": -100}); //圆心 this.ccelement.hide(); //外框隐藏 this.elementbox.attr({"stroke": "#000000", "stroke-width": 0.5}).hide(); //中心线隐藏 this.centerLineX.hide(); this.centerLineY.hide(); this.$elementctrl1.hide(); this.$elementctrl4.hide(); this.selected = false; //完成情况的显示 if (this.completeState != 0) { var name = "divshow_" + this.id; $("#" + name).hide(); } }, setText: function (wenbenid) { //得到文本框的值,重新赋值给text //Raphaël\nkicks\nbutt! var tvalue = $(".taskinput input").val(); var temp = tvalue; if ($.trim(tvalue) != "" && wenbenid == this.id) { var zishu = Math.floor(this.w / 14); //一行可显示的中文字数 var hangshu = parseInt(tvalue.length / zishu) + 1; //行数 var arr = []; if (tvalue.length > zishu) { for (var j = 0; j < hangshu; j++) { for (var i = j * zishu; i < (j + 1) * zishu; i = i + 1) { if (tvalue[i]) { if (arr[j]) { arr[j] += tvalue[i]; } else { arr[j] = tvalue[i]; } } } } temp = arr.join('\n'); } this.text.attr({"text": temp}); $(".taskinput input").val("");//清空 } }, removeSubElement: function (elem) { //删除子元素 var _that = this; $.each(this.subElement, function (index, ele) { if (ele && ele.id == elem.id) { _that.subElement.splice(index, 1); } }); }, removeElement: function () { //子流程删除本身 this.element.remove(); this.centerLineX.remove(); this.centerLineY.remove(); this.elementbox.remove(); this.$elementctrl1.remove(); this.$elementctrl4.remove(); this.text.remove(); this.ccelement.remove(); //小菜单回归原位 $(".right").css({"left": -100, "top": -100}); //文本框回归 $(".taskinput").css({"left": -100, "top": -100}); //移除相关的线 var tempoutlines = []; $.each(this.lineout, function (index, line) { tempoutlines.push(line); }); $.each(tempoutlines, function (index, line) { line && line.removeElement(); }); var tempinlines = []; $.each(this.linein, function (index, line) { tempinlines.push(line); }); $.each(tempinlines, function (index, line) { line && line.removeElement(); }); }, removeOutLine: function (line) { var _that = this; $.each(this.lineout, function (index, elem) { if (elem && elem.id == line.id) { _that.lineout.splice(index, 1); } }) }, removeInLine: function (line) { var _that = this; $.each(this.linein, function (index, elem) { if (elem && elem.id == line.id) { _that.linein.splice(index, 1); } }) }, getText: function () { return this.text.attr("text"); } }) var FlowDesigner = function (options) { //构造函数 if (!(this instanceof FlowDesigner)) { console.log("FlowDesigner 是一个构造函数,应该用new关键字调用!"); return; } this.allnodes = {};//设计器上所有节点集合 this.alllines = {};//设计器上所有线条 this.addPoint = false;//是否正在线上加圆点的状态 this.subtractPoint = false; //是否减点状态 //默认配置参数 this._DEFALUTS_ = { "id": "container", "mode": "design", //设计模式design 查看模式view "height": 500, "width": 500, "dx": 0, //画布距离屏幕的x偏移量 "dy": 46, //画布距离屏幕的y偏移量 "startmax": 0, //计数 "taskmax": 0 //任务编号计数 , "linemax": 0 //线段编号计数 , "smallcirclemax": 0 //线上的小圆点编号累加 , "endmax": 0 //end节点计数 , "gatewaymax": 0 //网关的计数 , "subprocessmax": 0 //子流程的计数 } $.extend(this._DEFALUTS_, options || {}); this.paper = Raphael(this._DEFALUTS_.id, this._DEFALUTS_.width, this._DEFALUTS_.height); $("#" + this._DEFALUTS_.id).css({ "width": this._DEFALUTS_.width, "height": this._DEFALUTS_.height }); var _that = this; $("#" + this._DEFALUTS_.id).click(function (e) { //IE8下点击画布是DIV if ((e.target.nodeName == "DIV" || e.target.nodeName == "svg") && (_that.addPoint == false && _that.subtractPoint == false)) { _that.allUnSelect(); } else if (_that.addPoint == true) { //检查落点是否在线上 var x = e.clientX - _that._DEFALUTS_.dx; var y = e.clientY - _that._DEFALUTS_.dy; //console.log("x,y",x,y); var x1, y1, x2, y2, tempy, tempx; var arrLen = 0; $.each(_that.alllines, function (i, line) { arrLen = line.linepointsxy.length; //console.log(line.linepointsxy); $.each(line.linepointsxy, function (index, arr) { if (index + 1 < arrLen) { var x1 = arr[1]; var y1 = arr[2]; var x2 = line.linepointsxy[index + 1][1]; var y2 = line.linepointsxy[index + 1][2]; //console.log("察看",x1,y1,x2,y2); if (floatToFix4(x1) != floatToFix4(x2)) { //x1!=x2 tempy = _that.getYLinePointFormula(x1, y1, x2, y2, x); var max = Math.max(x1, x2); var min = Math.min(x1, x2); //console.log("tempy",tempy); if (floatToFix4(tempy - 1.5) <= floatToFix4(y) && floatToFix4(y) <= floatToFix4(tempy + 1.5) && x > min && x < max) { //表示找到线和点的位置 //加入到该线段上 _that.addLinePosition(line, index + 1, x, y); // //关掉加点状态 // _that.addPoint=false; return false; } } else { tempx = _that.getXLinePointFormula(x1, y1, x2, y2, y); //console.log("tempx",tempx); var max = Math.max(y1, y2); var min = Math.min(y1, y2); if (floatToFix4(tempx - 1.5) <= floatToFix4(x) && floatToFix4(x) <= floatToFix4(tempx + 1.5) && y > min && y < max) { //表示找到线和点的位置 //加入到该线段上 _that.addLinePosition(line, index + 1, x, y); // //关掉加点状态 // _that.addPoint=false; return false; } } } }); }) } }) } FlowDesigner.prototype.getScrollx = function () { //出现滚动条时的dx return parseInt($("#" + this._DEFALUTS_.id).parent().scrollLeft()); } FlowDesigner.prototype.getScrolly = function () { //出现滚动条时的dx return parseInt($("#" + this._DEFALUTS_.id).parent().scrollTop()); } FlowDesigner.prototype.zoomin = function () { var options = this.getOptions(); var width = options.width * 1.1; var height = options.height * 1.1; options.width = width; options.height = height; this.paper.setSize(width, height); $("#" + this._DEFALUTS_.id).css({"height": height, "width": width}); } FlowDesigner.prototype.zoomout = function () { var options = this.getOptions(); var width = options.width / 1.1; var height = options.height / 1.1; options.width = width; options.height = height; this.paper.setSize(width, height); $("#" + this._DEFALUTS_.id).css({"height": height, "width": width}); } FlowDesigner.prototype.getOptions = function () { return this._DEFALUTS_; } /*start编号累加*/ FlowDesigner.prototype.createStartNodeNum = function () { this._DEFALUTS_.startmax++; return this._DEFALUTS_.startmax; } /*usertask编号累加*/ FlowDesigner.prototype.createTaskNum = function () { this._DEFALUTS_.taskmax++; return this._DEFALUTS_.taskmax; } /*线编号累加*/ FlowDesigner.prototype.createLineNum = function () { this._DEFALUTS_.linemax++; return this._DEFALUTS_.linemax; } /*线上的小圆点编号累加*/ FlowDesigner.prototype.createSmallCircleNodeNum = function () { this._DEFALUTS_.smallcirclemax++; return this._DEFALUTS_.smallcirclemax; } /*线上的end编号累加*/ FlowDesigner.prototype.createEndNodeNum = function () { this._DEFALUTS_.endmax++; return this._DEFALUTS_.endmax; } /*线上的gateway编号累加*/ FlowDesigner.prototype.createGatewayNum = function () { this._DEFALUTS_.gatewaymax++; return this._DEFALUTS_.gatewaymax; } /*线上的子流程编号累加*/ FlowDesigner.prototype.createSubprocessNum = function () { this._DEFALUTS_.subprocessmax++; return this._DEFALUTS_.subprocessmax; } /*清除画布所有元素*/ FlowDesigner.prototype.clear = function () { var _that = this; $.messager.confirm('再次确认', '您确定要清除画布中所有元素?', function (r) { if (r) { $.each(_that.allnodes, function (name, elem) { elem.removeElement(); }); $.each(_that.alllines, function (name, elem) { elem.removeElement(); }) _that.paper.clear(); //全部元素移除 _that.allnodes = {}; _that.alllines = {}; } }); } /*清除画布所有元素,不需要确认*/ FlowDesigner.prototype.clear2 = function () { var _that = this; $.each(_that.allnodes, function (name, elem) { elem.removeElement(); }); $.each(_that.alllines, function (name, elem) { elem.removeElement(); }) _that.paper.clear(); //全部元素移除 _that.allnodes = {}; _that.alllines = {}; } /*去掉所有元素的选择状态*/ FlowDesigner.prototype.allUnSelect = function () { //循环所有节点,调用自身的unselect方法 $.each(this.allnodes, function (name, elem) { elem.unSelect(); }); //循环所有线,调用自身的unselect方法 $.each(this.alllines, function (name, elem) { elem.unSelect(); }); } /*找出所有指定类型的节点*/ FlowDesigner.prototype.findAllNodeByType = function (type) { var findAll = []; $.each(this.allnodes, function (name, elem) { if (elem.type == type) { findAll.push({"id": elem.id, "text": elem.getText()}); } }); return findAll; } /*两个方块间的碰撞检测moveid是正在移动元素的类实例的id ,后面的4个参数是移动元素的四个坐标,返回一个被撞元素 */ FlowDesigner.prototype.collision = function (move, L1, R1, T1, B1) { var bpz = null; //被碰撞元素 if (move.type != "subProcess") { $.each(this.allnodes, function (id, elem) { if (id != move.id) { if (elem.type != "subProcess") { if (pz(L1, R1, T1, B1, elem.coordinate[0], elem.coordinate[1], elem.coordinate[2], elem.coordinate[3])) { bpz = elem; elem.elementbox.show().attr({"stroke": "#ff0000", "stroke-width": 2}); //elem.$moveDiv.css({"borderColor":"#ff0000","zIndex":0}); return false; } else { elem.elementbox.attr({"stroke": "#000000", "stroke-width": 0.5}); //elem.$moveDiv.css({"borderColor":"#000000","zIndex":-1}); } } else { if (pz(L1, R1, T1, B1, elem.coordinate[0], elem.coordinate[1], elem.coordinate[2], elem.coordinate[3]) && (move.parentElem == null || elem.id != move.parentElem.id)) { bpz = elem; //绿色 elem.elementbox.show().attr({"stroke": "#84ff20", "stroke-width": 2}); //elem.$moveDiv.css({"borderColor":"#ff0000","zIndex":0}); return false; } else { elem.elementbox.attr({"stroke": "#000000", "stroke-width": 0.5}); //elem.$moveDiv.css({"borderColor":"#000000","zIndex":-1}); } } } }); } else {//移动元素是子流程时 $.each(this.allnodes, function (id, elem) { if (id != move.id) { if (elem.parentElem == null) {//只有外部元素才匹配 if (pz(L1, R1, T1, B1, elem.coordinate[0], elem.coordinate[1], elem.coordinate[2], elem.coordinate[3])) { bpz = elem; elem.elementbox.show().attr({"stroke": "#ff0000", "stroke-width": 2}); //elem.$moveDiv.css({"borderColor":"#ff0000","zIndex":0}); return false; } else { elem.elementbox.attr({"stroke": "#000000", "stroke-width": 0.5}); //elem.$moveDiv.css({"borderColor":"#000000","zIndex":-1}); } } } }); } return bpz; } FlowDesigner.prototype.collisionSubProcess = function (L1, R1, T1, B1) { var bpz = null; //被碰撞元素 $.each(this.allnodes, function (id, elem) { if (elem.type == "subProcess") { if (pz(L1, R1, T1, B1, elem.coordinate[0], elem.coordinate[1], elem.coordinate[2], elem.coordinate[3])) { bpz = elem; return false; } } }); return bpz; } //判断当前点是否在区域内 FlowDesigner.prototype.lineFootholdDraging = function (startNode, sourcex, sourcey) { $.each(this.allnodes, function (id, elem) { if (elem.type == "userTask" || elem.type == "end" || elem.type == "gateway" || (elem.type == "subProcess" && (startNode.parentElem == null || startNode.parentElem.id != elem.id))) { if (elem.coordinate[0] <= sourcex && sourcex <= elem.coordinate[1] && elem.coordinate[2] <= sourcey && sourcey < elem.coordinate[3]) { //在区域内 elem.elementbox.attr({"stroke": "#84ff20", "stroke-width": 4}).show(); } else { elem.elementbox.attr({"stroke": "#000000", "stroke-width": 0.5}).hide(); } } }); } //判断当前的点是否落在区域块中,并返回该对象 FlowDesigner.prototype.lineFoothold = function (startNode, sourcex, sourcey) { var target = null; $.each(this.allnodes, function (id, elem) { if (elem.type == "userTask" || elem.type == "end" || elem.type == "gateway" || (elem.type == "subProcess" && (startNode.parentElem == null || startNode.parentElem.id != elem.id))) { if (elem.coordinate[0] <= sourcex && sourcex <= elem.coordinate[1] && elem.coordinate[2] <= sourcey && sourcey < elem.coordinate[3]) { //在区域内 target = elem; return false; } } }); return target; } /*元素碰撞:前4个是移动元素坐标,后面4个被撞元素坐标 */ function pz(L1, R1, T1, B1, L2, R2, T2, B2) { if (R1 < L2 || L1 > R2 || B1 < T2 || T1 > B2) {//碰不着 return false; } else { return true; } } /*其他元素的中心线显示:两个方块间的碰撞检测move是正在移动元素的类实例,后面的4个参数是移动元素的四个坐标 */ FlowDesigner.prototype.collisionCenterLine = function (move, L1, R1, T1, B1) { var bpzcentery = []; //被碰撞中心元素集合,选出最近的元素,做吸附对齐,y方向。 var bpzcenterx = []; //被碰撞中心元素集合,选出最近的元素,做吸附对齐,x方向。 var bpzcenter = [null, null]; //有2个元素,第一个元素是y方向上的对齐元素,第二个元素是x方向上的对齐元素。 $.each(this.allnodes, function (id, elem) { if (move.parentElem != null) { //有父元素的时候 if (elem.type == "subProcess" && elem.id == move.parentElem.id) { //基本元素move,在自家子流程之内移动,不匹配自家父元素 return true; //跳出本次循环 } else { if (id != move.id && elem.parentElem != null && elem.parentElem.id == move.parentElem.id) { //2.基本元素move,自家子流程内,只有和自家的其它元素匹配 switch (pz2(L1, R1, T1, B1, elem.coordinate[0], elem.coordinate[1], elem.coordinate[2], elem.coordinate[3])) { case "竖线": elem.centerLineY.show().toBack(); bpzcentery.push(elem); break; case "横线": elem.centerLineX.show().toBack(); bpzcenterx.push(elem); break; case "": elem.centerLineX.hide(); elem.centerLineY.hide(); break; } } } } else {//没有父元素的时候,也不匹配子流程内部的元素 if (id != move.id && elem.parentElem == null) { switch (pz2(L1, R1, T1, B1, elem.centerLineCoordinate[0], elem.centerLineCoordinate[1], elem.centerLineCoordinate[2], elem.centerLineCoordinate[3])) { case "竖线": elem.centerLineY.show().toBack(); bpzcentery.push(elem); break; case "横线": elem.centerLineX.show().toBack(); bpzcenterx.push(elem); break; case "": elem.centerLineX.hide(); elem.centerLineY.hide(); break; } } } }); //得到最贴近的2个元素,第一个是y方向,第二个是x方向 if (bpzcentery.length >= 2) { var centerx = (L1 + R1) / 2; var minIndex = 0; $.each(bpzcentery, function (index, elem) { if (index > 0 && Math.abs((elem.centerLineCoordinate[0] + elem.centerLineCoordinate[1]) / 2 - centerx) < Math.abs((bpzcentery[minIndex].centerLineCoordinate[0] + bpzcentery[minIndex].centerLineCoordinate[0]) / 2 - centerx)) { minIndex = index; } }) bpzcenter[0] = bpzcentery[minIndex]; } else if (bpzcentery.length == 1) { bpzcenter[0] = bpzcentery[0]; } else if (bpzcentery.length == 0) { bpzcenter[0] = null; } //第二个是x方向 if (bpzcenterx.length >= 2) { var centery = (T1 + B1) / 2; var minIndex = 0; $.each(bpzcenterx, function (index, elem) { if (index > 0 && Math.abs((elem.centerLineCoordinate[2] + elem.centerLineCoordinate[3]) / 2 - centery) < Math.abs((bpzcenterx[minIndex].centerLineCoordinate[2] + bpzcenterx[minIndex].centerLineCoordinate[3]) / 2 - centery)) { minIndex = index; } }) bpzcenter[1] = bpzcenterx[minIndex]; } else if (bpzcenterx.length == 1) { bpzcenter[1] = bpzcenterx[0]; } else if (bpzcenterx.length == 0) { bpzcenter[1] = null; } return bpzcenter; } /*子流程的中心线碰撞move是子流程 其他元素的中心线显示:两个方块间的碰撞检测move是正在移动元素的类实例的 ,后面的4个参数是移动元素的四个坐标 */ FlowDesigner.prototype.subProcessCollisionCenterLine = function (move, L1, R1, T1, B1) { var bpzcentery = []; //被碰撞中心元素集合,选出最近的元素,做吸附对齐,y方向。 var bpzcenterx = []; //被碰撞中心元素集合,选出最近的元素,做吸附对齐,x方向。 var bpzcenter = [null, null]; //有2个元素,第一个元素是y方向上的对齐元素,第二个元素是x方向上的对齐元素。 $.each(this.allnodes, function (id, elem) { if (id != move.id && elem.parentElem == null) { //只和外部元素碰撞 switch (pz2(L1, R1, T1, B1, elem.centerLineCoordinate[0], elem.centerLineCoordinate[1], elem.centerLineCoordinate[2], elem.centerLineCoordinate[3])) { case "竖线": elem.centerLineY.show().toBack(); bpzcentery.push(elem); break; case "横线": elem.centerLineX.show().toBack(); bpzcenterx.push(elem); break; case "": elem.centerLineX.hide(); elem.centerLineY.hide(); break; } } }); //得到最贴近的2个元素,第一个是y方向,第二个是x方向 if (bpzcentery.length >= 2) { var centerx = (L1 + R1) / 2; var minIndex = 0; $.each(bpzcentery, function (index, elem) { if (index > 0 && Math.abs((elem.centerLineCoordinate[0] + elem.centerLineCoordinate[1]) / 2 - centerx) < Math.abs((bpzcentery[minIndex].centerLineCoordinate[0] + bpzcentery[minIndex].centerLineCoordinate[0]) / 2 - centerx)) { minIndex = index; } }) bpzcenter[0] = bpzcentery[minIndex]; } else if (bpzcentery.length == 1) { bpzcenter[0] = bpzcentery[0]; } else if (bpzcentery.length == 0) { bpzcenter[0] = null; } //第二个是x方向 if (bpzcenterx.length >= 2) { var centery = (T1 + B1) / 2; var minIndex = 0; $.each(bpzcenterx, function (index, elem) { if (index > 0 && Math.abs((elem.centerLineCoordinate[2] + elem.centerLineCoordinate[3]) / 2 - centery) < Math.abs((bpzcenterx[minIndex].centerLineCoordinate[2] + bpzcenterx[minIndex].centerLineCoordinate[3]) / 2 - centery)) { minIndex = index; } }) bpzcenter[1] = bpzcenterx[minIndex]; } else if (bpzcenterx.length == 1) { bpzcenter[1] = bpzcenterx[0]; } else if (bpzcenterx.length == 0) { bpzcenter[1] = null; } return bpzcenter; } //小圆点的碰撞 FlowDesigner.prototype.collisionSelfCenterLine = function (small, L1, R1, T1, B1) { var bpzcenter = [null, null]; var start = small.belongLine.nodestart; var L2 = start.centerLineCoordinate[0]; var R2 = start.centerLineCoordinate[1]; var T2 = start.centerLineCoordinate[2]; var B2 = start.centerLineCoordinate[3]; var end = small.belongLine.nodeend; var L3 = end.centerLineCoordinate[0]; var R3 = end.centerLineCoordinate[1]; var T3 = end.centerLineCoordinate[2]; var B3 = end.centerLineCoordinate[3]; if (L2 < L1 && R1 < R2) { bpzcenter[0] = start.centerpoint[0]; } if (T3 < T1 && B1 < B3) { bpzcenter[1] = end.centerpoint[1]; } if (L3 < L1 && R1 < R3) { bpzcenter[0] = end.centerpoint[0]; } if (T2 < T1 && B1 < B2) { bpzcenter[1] = start.centerpoint[1]; } return bpzcenter; } /*元素中心线碰撞:前4个是移动元素坐标,后面4个被撞元素坐标*/ function pz2(L1, R1, T1, B1, L2, R2, T2, B2) { var ret = ""; if ((L1 < L2 && R1 > L2) || (L1 < R2 && R1 > R2) || (L1 < L2 && R2 < R1)) { ret = "竖线"; } else if ((T1 < T2 && B1 > T2) || (T1 < B2 && B1 > B2) || (T1 < T2 && B2 < B1)) { //console.log(L1, R1, T1, B1,"," ,L2, R2, T2, B2); ret = "横线"; } return ret; } /*两个点之间形成公式,输入x,得到y轴坐标 */ FlowDesigner.prototype.getYLinePointFormula = function (x1, y1, x2, y2, x) { if (floatToFix4(x1) != floatToFix4(x2)) { var y = y2 + (x - x2) * (y1 - y2) / (x1 - x2); } else { y = y2; } return y; } /*两个点之间形成公式,输入y,得到x轴坐标 */ FlowDesigner.prototype.getXLinePointFormula = function (x1, y1, x2, y2, y) { if (floatToFix4(y1) != floatToFix4(y2)) { var x = x2 + (x1 - x2) * (y - y2) / (y1 - y2); } else { var x = x2; } return x; } //通过对象id找到指定元素类实例 FlowDesigner.prototype.FindElementById = function (id) { var find = null; $.each(this.allnodes, function (name, elem) { if (name == id) { find = elem; } }); if (find == null) { //如果不是元素,则查找线段 $.each(this.alllines, function (name, elem) { if (name == id) { find = elem; } }); } return find; } //删除元素 FlowDesigner.prototype.removeElement = function (obj) { var _that = this; $.messager.confirm('再次确认', '您确定要删除该元素吗?', function (r) { if (r) { var elemid = $(obj).closest(".right").attr("tempid"); var elem = _that.FindElementById(elemid); elem && elem.removeElement();//画布上的元素清除 if (elem && elem.type != "line") { delete _that.allnodes[elemid]; //删除元素 } if (elem && elem.type == "line") { delete _that.alllines[elemid]; //删除线 } } }); } //得到目标的箭头坐标 ,只适合于目标是矩形 FlowDesigner.prototype.getArrowPosXY = function (startNode, dropElem) { //线的开始坐标,即startNode的中心点,但需要获得目标节点边框上的点,作为线的(箭头)的最终点 //1.判断开始节点和目标节点的位置关系。2.得到两个节点中心点间的直线公式,算出箭头中心点。3.通过startNode的中心点和箭头中心点,创建线段对象。 var pos = -1; if (startNode.coordinate[0] >= dropElem.coordinate[1] && startNode.coordinate[3] <= dropElem.coordinate[2]) { //Start元素在目标元素的右上面 pos = 21; } else if (startNode.coordinate[1] <= dropElem.coordinate[0] && startNode.coordinate[3] <= dropElem.coordinate[2]) { //Start元素在目标元素的左上面 pos = 20; } else if (startNode.coordinate[1] <= dropElem.coordinate[0] && startNode.coordinate[2] >= dropElem.coordinate[3]) { //Start元素在目标元素的左下面 pos = 30; } else if (startNode.coordinate[0] >= dropElem.coordinate[1] && startNode.coordinate[2] >= dropElem.coordinate[3]) { //Start元素在目标元素的右下面 pos = 13; } else if (startNode.coordinate[3] <= dropElem.coordinate[2]) { pos = 2; //Start元素在目标元素的上面 } else if (startNode.coordinate[1] < dropElem.coordinate[0]) { pos = 0;//Start元素在目标元素的左边 } else if (startNode.coordinate[2] >= dropElem.coordinate[3]) { pos = 3; //Start元素在目标元素的下面 } else if (startNode.coordinate[0] >= dropElem.coordinate[1]) { pos = 1; //Start元素在目标元素的右面 } var x = 0; var y = 0; var x1 = 0, y1 = 0; if (pos != -1) { switch (pos) { case 0: //Start元素在目标元素的左边 x = dropElem.coordinate[0]; y = flowDesigner.getYLinePointFormula(startNode.centerpoint[0], startNode.centerpoint[1], dropElem.centerpoint[0], dropElem.centerpoint[1], x); break; case 1: //Start元素在目标元素的右面 x = dropElem.coordinate[1]; y = flowDesigner.getYLinePointFormula(startNode.centerpoint[0], startNode.centerpoint[1], dropElem.centerpoint[0], dropElem.centerpoint[1], x); break; case 2://Start元素在目标元素的上面 y = dropElem.coordinate[2]; x = flowDesigner.getXLinePointFormula(startNode.centerpoint[0], startNode.centerpoint[1], dropElem.centerpoint[0], dropElem.centerpoint[1], y); break; case 3://Start元素在目标元素的下面 y = dropElem.coordinate[3]; x = flowDesigner.getXLinePointFormula(startNode.centerpoint[0], startNode.centerpoint[1], dropElem.centerpoint[0], dropElem.centerpoint[1], y); break; case 21: //Start元素在目标元素的右上 y1 = dropElem.coordinate[2]; //2 x1 = flowDesigner.getXLinePointFormula(startNode.centerpoint[0], startNode.centerpoint[1], dropElem.centerpoint[0], dropElem.centerpoint[1], y1); if (dropElem.x < x1 && x1 < (dropElem.x + dropElem.w)) { x = x1; y = y1; } else { x1 = dropElem.coordinate[1]; y1 = flowDesigner.getYLinePointFormula(startNode.centerpoint[0], startNode.centerpoint[1], dropElem.centerpoint[0], dropElem.centerpoint[1], x1); x = x1; y = y1; } break; case 20: //2和0 ,Start元素在目标元素的左上 y1 = dropElem.coordinate[2]; //2 x1 = flowDesigner.getXLinePointFormula(startNode.centerpoint[0], startNode.centerpoint[1], dropElem.centerpoint[0], dropElem.centerpoint[1], y1); if (dropElem.x < x1 && x1 < (dropElem.x + dropElem.w)) { x = x1; y = y1; } else { x1 = dropElem.coordinate[0]; //0 y1 = flowDesigner.getYLinePointFormula(startNode.centerpoint[0], startNode.centerpoint[1], dropElem.centerpoint[0], dropElem.centerpoint[1], x1); x = x1; y = y1; } break; case 13: //1和3,Start元素在目标元素的右下面 y1 = dropElem.coordinate[3]; //3 x1 = flowDesigner.getXLinePointFormula(startNode.centerpoint[0], startNode.centerpoint[1], dropElem.centerpoint[0], dropElem.centerpoint[1], y1); if (dropElem.x < x1 && x1 < dropElem.x + dropElem.w) { x = x1; y = y1; } else { x1 = dropElem.coordinate[1]; //1的判断 Start元素在目标元素的右面 y1 = flowDesigner.getYLinePointFormula(startNode.centerpoint[0], startNode.centerpoint[1], dropElem.centerpoint[0], dropElem.centerpoint[1], x1); x = x1; y = y1; } break; case 30: //0和3,Start元素在目标元素的左下 y1 = dropElem.coordinate[3]; //3 x1 = flowDesigner.getXLinePointFormula(startNode.centerpoint[0], startNode.centerpoint[1], dropElem.centerpoint[0], dropElem.centerpoint[1], y1); if (dropElem.x < x1 && x1 < (dropElem.x + dropElem.w)) { x = x1; y = y1; } else { x1 = dropElem.coordinate[0]; //0 y1 = flowDesigner.getYLinePointFormula(startNode.centerpoint[0], startNode.centerpoint[1], dropElem.centerpoint[0], dropElem.centerpoint[1], x1); x = x1; y = y1; } break; } } return {"x": x, "y": y} } //得到目标的箭头坐标,目标是end节点 FlowDesigner.prototype.getCircleArrowPosXY = function (startNode, dropElem) { var linestr = "M" + startNode.centerpoint [0] + "," + startNode.centerpoint[1] + "L" + dropElem.centerpoint[0] + "," + dropElem.centerpoint[1]; var linehide = this.paper.path(linestr).hide(); var linelength = linehide.getTotalLength(); var point = linehide.getPointAtLength(linelength - dropElem.r); linehide.remove(); return {"x": point.x, "y": point.y} } //得到线的出发点 FlowDesigner.prototype.getStartPosXY = function (startNode, dropElem) { var retPoint = null; switch (startNode.type) { case "smallcircle": case "start": retPoint = this.getCircleStartPosXY(startNode, dropElem); break; case "gateway": case "subProcess": case "userTask": retPoint = this.getQuadrangleStartPosXY(startNode, dropElem); break; } return retPoint; } //得到线的出发点,开始节点是圆 FlowDesigner.prototype.getCircleStartPosXY = function (startNode, dropElem) { var linestr = "M" + startNode.centerpoint [0] + "," + startNode.centerpoint[1] + "L" + dropElem.centerpoint[0] + "," + dropElem.centerpoint[1]; var linehide = this.paper.path(linestr).hide(); var point = linehide.getPointAtLength(startNode.r); linehide.remove(); return {"x": point.x, "y": point.y} } //得到线的出发点,开始节点是四边形 FlowDesigner.prototype.getQuadrangleStartPosXY = function (startNode, dropElem) { var point = null; var a = {"x": startNode.centerpoint[0], "y": startNode.centerpoint[1]}; var b = {"x": dropElem.centerpoint[0], "y": dropElem.centerpoint[1]}; //console.log("startNode",startNode); //console.log("dropElem",dropElem); $.each(startNode.fourpoint, function (index, elem) { //循环4个点,依次形成4条线cd,分别和ab,求交点,求到一个交点就结束 //console.log(a,b,dropElem.fourpoint[index%4],dropElem.fourpoint[(index+1)%4]); point = segmentsIntr(a, b, startNode.fourpoint[index % 4], startNode.fourpoint[(index + 1) % 4]); if (point != false) { return false; } }); return point; } //得到目标的箭头坐标,目标是Gateway节点 FlowDesigner.prototype.getGatewayArrowPosXY = function (startNode, dropElem) { var point = null; var a = {"x": startNode.centerpoint[0], "y": startNode.centerpoint[1]}; var b = {"x": dropElem.centerpoint[0], "y": dropElem.centerpoint[1]}; //console.log("startNode",startNode); //console.log("dropElem",dropElem); $.each(dropElem.fourpoint, function (index, elem) { //循环4个点,依次形成4条线cd,分别和ab,求交点,求到一个交点就结束 //console.log(a,b,dropElem.fourpoint[index%4],dropElem.fourpoint[(index+1)%4]); point = segmentsIntr(a, b, dropElem.fourpoint[index % 4], dropElem.fourpoint[(index + 1) % 4]); if (point != false) { return false; } }); return point; } //得到两线的交点(ab是一条线,cd是另一条线) function segmentsIntr(a, b, c, d) { /** 1 解线性方程组, 求线段交点. **/ // 如果分母为0 则平行或共线, 不相交 var denominator = (b.y - a.y) * (d.x - c.x) - (a.x - b.x) * (c.y - d.y); if (denominator == 0) { return false; } // 线段所在直线的交点坐标 (x , y) var x = ((b.x - a.x) * (d.x - c.x) * (c.y - a.y) + (b.y - a.y) * (d.x - c.x) * a.x - (d.y - c.y) * (b.x - a.x) * c.x) / denominator; var y = -((b.y - a.y) * (d.y - c.y) * (c.x - a.x) + (b.x - a.x) * (d.y - c.y) * a.y - (d.x - c.x) * (b.y - a.y) * c.y) / denominator; /** 2 判断交点是否在两条线段上 **/ if ( // 交点在线段1上 (x - a.x) * (x - b.x) <= 0 && (y - a.y) * (y - b.y) <= 0 // 且交点也在线段2上 && (x - c.x) * (x - d.x) <= 0 && (y - c.y) * (y - d.y) <= 0 ) { // 返回交点p return { x: x, y: y } } //否则不相交 return false; } //得到线上的点,并且判断自身是否在直线上,如果在者不变,如果不在就按两点的距离存在的点数来设置。startNode:开始节点,endNode:结束节点,selfNode:自身本来的节点,length ,节点数+1,线被节点分成几段,index:第几个 FlowDesigner.prototype.getNewSmallCirclePosXY = function (startNode, endNode, selfNode, length, index) { //先判断是否在直线上 if (floatToFix4(startNode.x) == floatToFix4(selfNode[1]) || floatToFix4(startNode.y) == floatToFix4(selfNode[2])) { return {"x": selfNode[1], "y": selfNode[2]}; } //不在直线上 var linestr = "M" + startNode.x + "," + startNode.y + "L" + endNode.x + "," + endNode.y; var linehide = this.paper.path(linestr).hide(); var linelength = linehide.getTotalLength(); var point = linehide.getPointAtLength(linelength * index / length); linehide.remove(); return {"x": point.x, "y": point.y}; } //添加元素 FlowDesigner.prototype.addElement = function (options) { switch (options.type) { case "start": var startNode = new Start(this, options); startNode.init(); this.allnodes[startNode.id] = startNode; return startNode; break; case "userTask": var userTaskNode = new UserTask(this, options); userTaskNode.init(); this.allnodes[userTaskNode.id] = userTaskNode; return userTaskNode; break; case "line": var line = new Line(this, options); line.init(); this.alllines[line.id] = line; return line; break; case "end": var endNode = new End(this, options); endNode.init(); this.allnodes[endNode.id] = endNode; return endNode; break; case "gateway": var gatewayNode = new Gateway(this, options); gatewayNode.init(); this.allnodes[gatewayNode.id] = gatewayNode; return gatewayNode; break; case "subProcess": var subProcessNode = new SubProcess(this, options); subProcessNode.init(); this.allnodes[subProcessNode.id] = subProcessNode; return subProcessNode; break; } } //设置线的加点状态 FlowDesigner.prototype.setAddPointStatus = function () { this.addPoint = !this.addPoint; if (this.addPoint) { this.allUnSelect(); } return this.addPoint; } FlowDesigner.prototype.setSubtractPointStatus = function () { this.subtractPoint = !this.subtractPoint; if (this.subtractPoint) { this.allUnSelect(); } return this.subtractPoint; } //加入线上的小圆点 line表示所加入的线,在index位置上插入点(pointx,pointy) FlowDesigner.prototype.addLinePosition = function (line, index, pointx, pointy) { line.linepointsxy.splice(index, 0, ["L", pointx, pointy]); line.linestr = Raphael.parsePathString(line.linepointsxy); //重绘小圆点 line.redrawSmallCircle(true); } return FlowDesigner; });