JS组件系列——JsPlumb流程图及相关效果详解
前言:之前项目里面用到了Web里面的拖拽流程图的技术JsPlumb,其实真不算难,不过项目里面用HTML做的一些类似flash的效果,感觉还不错,在此分享下。
Jsplumb官网:https://jsplumbtoolkit.com
GitHub:https://github.com/sporritt/jsplumb/
一、效果图展示
1、从左边拖动元素到中间区域,然后连线
2、连线类型可以自定义:这里定义为直线、折线、曲线。实际项目中根据业务我们定义为分装线、分装支线、总装线等
3、鼠标拖动区域选中元素,并且选中元素统一拖动位置。
4、对选中的元素左对齐。
5、对选中元素居中对齐
6、右对齐
7、上对齐
8、垂直居中对齐
9、下对齐
10、根据第一个选中的元素上下靠拢
11、根据第一个选中的元素左右靠拢
12、根据第一个选中的元素同高
13、根据第一个选中的元素同宽
14、选中元素顺时针旋转,点击一次旋转45度
15、选中元素逆时针旋转。
16、选中统一删除元素以及元素上面的连线
这里很多效果其实在项目中作用并不太大,很多单纯就是为了展示用的。没办法,领导要求,我们就只有做喽。
二、代码详解
这里涉及的效果比较多,可能要分多篇来介绍。这篇还是来看看构造流程图的核心技术:JsPlumb。
1、概述
关于JsPlumb的内容,园子里也有很多朋友做过分享,也有写得不错的博文。在此就简单说明下吧。jsPlumb是一个强大的JavaScript连线库,它可以将html中的元素用箭头、曲线、直线等连接起来,适用于开发Web上的图表、建模工具等。它同时支持jQuery+jQuery UI、MooTools和YUI3这三个JavaScript框架,十分强大。本项目中还是结合大家最熟悉的JQuery来讲解。并且还要注意的一点就是JsPlumb的浏览器兼容性,JsPlumb支持IE 6以上、火狐、谷歌等各种浏览器
2、使用
(1)引入JS文件
可以直接去官网上面下载最新的js库,由于JsPlumb需要JQuery的支持,按照网上的说法,它只兼容jQuery1.3.x及以上版本,并在jQuery UI 1.7.x、1.8.x及1.9.x上测试通过。所以我们需要下载较高一点版本的JQuery和JQuery UI。关于JsPlumb的内容只需要引用一个Js即可。类似
<script src="~/Content/jquery-1.9.1.min.js"></script> <script src="~/Content/jquery-ui-1.11.4.custom/jquery-ui.js"></script> <link href="~/Content/jquery-ui-1.11.4.custom/jquery-ui.min.css" rel="stylesheet" /> <script src="~/Content/jsPlumb-master/dist/js/jquery.jsPlumb-1.7.5.js"></script>
(2)初始化
使用JsPlumb需要注意一点,JsPlumb的连线的样式是由点确定的,也就是说点的样式里面包含了相关的属性来说明当使用此点来连线的时候,连线的样式应该是什么样的。
在我们项目里面,左边的模型区域,中间才是设计区域。那么要将一个元素从模型区域创建出来,就要用到我们JQuery UI里面的draggable和droppable事件。首先我们注册左边模型的draggable和中间区域的droppable事件。
cshtml页面代码,<div id="divContentLeftMenu">这个是左边模型的容器,<div id="divCenter"></div>表示中间区域容器。
<div id="divContentLeftMenu"> <div class="sidebar-menu" id="divSidebar"> <a href="#plantmodel" onclick="Resize()" class="nav-header menu-first collapsed" data-toggle="collapse">工厂模型</a> <ul id="plantmodel" class="nav nav-list collapse menu-second"> </ul> <a href="#artlinemodel" onclick="Resize()" class="nav-header menu-first collapsed" data-toggle="collapse">工艺段模型</a> <ul id="artlinemodel" class="nav nav-list collapse menu-second"> <li> <a href="#"> <div class="node radius" id="node4" dbtype="DTO_TM_ART_LINE"> <label>工段</label> </div> </a> </li> <li> <a href="#"> <div class="node" id="node5" dbtype="DTO_TM_ULOC"> <label>工位</label> </div> </a> </li> </ul> </div> </div> <div id="divCenter"></div>
Js代码:
首先我们定义几个点的样式的全局变量
//基本连接线样式 var connectorPaintStyle = { strokeStyle: "#1e8151", fillStyle: "transparent", radius: 5, lineWidth: 2 }; // 鼠标悬浮在连接线上的样式 var connectorHoverStyle = { lineWidth: 3, strokeStyle: "#216477", outlineWidth: 2, outlineColor: "white" }; var endpointHoverStyle = { fillStyle: "#216477", strokeStyle: "#216477" }; //空心圆端点样式设置 var hollowCircle = { DragOptions: { cursor: 'pointer', zIndex: 2000 }, endpoint: ["Dot", { radius: 7 }], //端点的形状 connectorStyle: connectorPaintStyle,//连接线的颜色,大小样式 connectorHoverStyle: connectorHoverStyle, paintStyle: { strokeStyle: "#1e8151", fillStyle: "transparent", radius: 5, lineWidth: 2 }, //端点的颜色样式 //anchor: "AutoDefault", isSource: true, //是否可以拖动(作为连线起点) connector: ["Straight", { stub: [0, 0], gap: 10, cornerRadius: 5, alwaysRespectStubs: true }], //连接线的样式种类有[Bezier],[Flowchart],[StateMachine ],[Straight ] isTarget: true, //是否可以放置(连线终点) maxConnections: -1, // 设置连接点最多可以连接几条线 connectorOverlays: [["Arrow", { width: 10, length: 10, location: 1 }]] };
然后再页面初始化完成之后注册事件
$(function(){ //左边区域的draggable事件 $("#divContentLeftMenu .node").draggable({ helper: "clone", scope: "plant" }); //中间拖拽区的drop事件 $("#divCenter").droppable({ scope: "plant", drop: function (event, ui) { // 创建工厂模型到拖拽区 CreateModel(ui, $(this)); } }); });
//1.创建模型(参数依次为:drop事件的ui、当前容器、id、当前样式)
function CreateModel(ui, selector) { //1.1 添加html模型 var modelid = $(ui.draggable).attr("id"); i++; var id = modelid + i; var cur_css = modelid; var type = $(ui.helper).attr("dbtype"); $(selector).append('<div class="node ' + cur_css + '" id="' + id + '" dbtype="' + type + '" parentid="' + $(selector).attr("id") + '" onclick="oInitElement.GetPropertiesByType(\'' + type + '\',this)" ondblclick="InitStation().DbClick(\'' + type + '\',this)" >' + $(ui.helper).html() + '</div>'); var left = parseInt(ui.offset.left - $(selector).offset().left); var top = parseInt(ui.offset.top - $(selector).offset().top); $("#" + id).css("left", left).css("top", top); //jsPlumb.setContainer($("#divCenter")); //1.2 添加连接点 jsPlumb.addEndpoint(id, { anchors: "RightMiddle" }, hollowCircle); jsPlumb.addEndpoint(id, { anchors: "LeftMiddle" }, hollowCircle); jsPlumb.addEndpoint(id, { anchors: "TopCenter" }, hollowCircle); jsPlumb.addEndpoint(id, { anchors: "BottomCenter" }, hollowCircle); jsPlumb.draggable(id); //1.3 注册实体可draggable和resizable $("#" + id).draggable({ containment: "parent", start: function () { startMove(); }, drag: function (event, ui) { MoveSelectDiv(event, ui, id); jsPlumb.repaintEverything(); }, stop: function () { jsPlumb.repaintEverything(); } }); $("#" + id).resizable({ resize: function () { jsPlumb.repaintEverything(); }, stop: function () { jsPlumb.repaintEverything(); //oInitElement.SendPropRequest("DTO_TM_PLANT", $(this)); } }); return id; };
重点来看看这一句:
jsPlumb.addEndpoint(id, { anchors: "RightMiddle" }, hollowCircle);
调用了JsPlumb里面的addEndpoint方法,第一个参数表示页面标签的id,第一个表示连线点的位置(RightMiddle、LeftMiddle、TopCenter、BottomCenter四个选项);第三参数表示点的样式以及连线的样式。没调用依次addEndpoint方法,元素上面就会多一个连线的节点。关于hollowCircle里面各个参数的意义,可以查看api。
还有一句多个地方都看到了:
jsPlumb.repaintEverything();
看字面意思大概能知道这句是干什么的,修复所有。当在中间区域拖动元素的时候,如果不带这一句,节点不会跟着元素一起移动。加上之后节点才会跟随标签移动。至此,最基础的JsPlumb连线就完成了。源码在下篇。