使用jsPlumb插件实现动态连线功能

这周去看了两天的羽毛球亚锦赛,工作有提前晚上加班做一些,但是技术文章却拉下了。
这段时间一直在寻找可以实现前端元素动态连线的功能,找了好几个库,考虑过用d3或者原生svg和canvas来实现,最后和同项目的同事商量后决定使用jsPlumb插件库来做。
jsPlumb是一个强大的JavaScript连线库,它可以将html中的元素用箭头、曲线、直线等连接起来,适用于开发Web上的图表、建模工具等,其实jsPlumb可能主要是用来做流程图的,它在实现这方面的功能上非常强大,我在项目中只使用了它少部分功能,来实现项目中连线的效果。


连线效果
initJSPlumb = () => {
    this.jsp = jsPlumb.getInstance({
        //锚点位置;对任何没有声明描点的Endpoint设置锚点,用于source及target节点
        Anchor: ["Right", "Left"], 
        Anchors: ["Right", "Left"],  //连线的source和target Anchor
        ConnectionsDetachable: false, //连线是否可用鼠标分离
        ConnectionOverlays: [  //连线的叠加组件,如箭头、标签
            ["Arrow", {  //箭头参数设置
                location: 1,
                visible: true,
                width: 11,
                length: 11,
                id: "ARROW",
                events: {
                    click: function () {
                    }
                }
            }],
            ["Label", {  //标签参数设置
                location: 0.1,
                id: "label",
                cssClass: "aLabel", //hover时label的样式名
                events: {
                    tap: function () {
                    }
                },
                visible: true
            }]
        ],
        Connector: "Bezier", //连线的类型,流程图(Flowchart)、贝塞尔曲线等
        //父级元素id;假如页面元素所在上层不同,最外层父级一定要设置
        Container: "module", 
        //如果请求不存在的Anchor、Endpoint或Connector,是否抛异常
        DoNotThrowErrors: false, 
        //通过jsPlumb.draggable拖拽元素时的默认参数设置
        DragOptions: {cursor: 'pointer', zIndex: 2000}, 
        DropOptions: {}, //target Endpoint放置时的默认参数设置
        Endpoint: "Dot", //端点(锚点)的样式声明
         //用jsPlumb.connect创建连接时,source端点和target端点的样式设置
        Endpoints: [null, null],
        EndpointOverlays: [], //端点的叠加物
        //端点的默认样式
        EndpointStyle: {fill: 'transparent', stroke: '#1565C0', radius: 4, 
            strokeWidth: 1}, 
        EndpointStyles: [null, null], //连线的source和target端点的样式
        //端点hover时的样式
        EndpointHoverStyle: {fill: '#1565C0', stroke: '#1565C0', radius: 4, 
            strokeWidth: 1}, 
        //连线的source和target端点hover时的样式
        EndpointHoverStyles: [null, null],
        //连线hover时的样式
        HoverPaintStyle: {stroke: '#1565C0', strokeWidth: 3}, 
        LabelStyle: {color: "black"}, //标签的默认样式,用css写法。
        LogEnabled: false, //是否开启jsPlumb内部日志
        Overlays: [], //连线和端点的叠加物
        MaxConnections: 10, //端点支持的最大连接数
        //连线样式
        PaintStyle: {stroke: '#1565C0', strokeWidth: 1, joinstyle: 'round'},
        ReattachConnections: true, //是否重新连接使用鼠标分离的线?
        RenderMode: "svg", //默认渲染模式
        Scope: "jsPlumb_DefaultScope", //范围,具有相同scope的点才可连接
        reattach: true,
    })
    this.jsp.bind('beforeDrop', this.jspBeforeDrop)
}

以上是初始化jsPlumb对象的函数。
接下来获取数据,加载页面的系统和编制模块。

fetchDataForLeft(data) {
    var jsonString_left = '[{"module_name":"crm系统","module_id":"A","nodes":[{"id":"A-1","text":"开始","position":"left"},{"id":"A-2","text":"过程","position":"left"},{"id":"A-3","text":"过程ing","position":"left"}]},{"module_name":"财务系统","module_id":"B","nodes":[{"id":"B-1","text":"开始","position":"left"}]}]';
    var jsonString_right = '[{"module_name":"年度预算编制","module_id":"C","nodes":[{"id":"C-1","text":"结束","position":"right"}]},{"module_name":"营收编制","module_id":"D","nodes":[{"id":"D-1","text":"结束","position":"right"}]}]';
    // var nodeData_left = JSON.parse(jsonString_left);
    //[{"entity":null,"id":"934D62BD0F8249B09F29EC9FA051E390","code":"1","name":"CRM????","systemType":null,"databaseType":null,"hostName":null,"databaseaName":null,"userName":null,"password":null,"created":null,"modified":null},{"entity":null,"id":"81ABCD2890E2460B90A9B8A0ACE3FABD","code":null,"name":"CRM系统","systemType":null,"databaseType":null,"hostName":null,"databaseaName":null,"userName":null,"password":null,"created":null,"modified":null},{"entity":null,"id":"9AE1B07886E54F3DB0082D46392DE774","code":null,"name":"CRM系统","systemType":null,"databaseType":null,"hostName":null,"databaseaName":null,"userName":null,"password":null,"created":null,"modified":null},{"entity":null,"id":"E6D29376AC86455DBC3518D12F28C5B0","code":null,"name":"CRM系统","systemType":null,"databaseType":null,"hostName":null,"databaseaName":null,"userName":null,"password":null,"created":null,"modified":null}]
    var nodeData_left = data;
    this.setState({
        nodes_left: nodeData_left,
    })
    //绘制左边点
    nodeData_left.map((node, index) => {
        this.setState({datas: node, nodes: node.fromModelList}, () => {
            this.initNodes(this.refs.nodes_left[index], 'left');
            // this.initEdges(nodeData.edges);
        });
    })
    //绘制右边点
    // nodeData_right.map((node, index) => {
    //     this.setState({data_right: node, node_right: node.toModelList}, () => {
    //         this.initNodes(this.refs.nodes_right[index], 'right');
    //         // this.initEdges(nodeData.edges);
    //     });
    // })
}
fetchDataForRight(data){
    var jsonString_left = '[{"module_name":"crm系统","module_id":"A","nodes":[{"id":"A-1","text":"开始","position":"left"},{"id":"A-2","text":"过程","position":"left"},{"id":"A-3","text":"过程ing","position":"left"}]},{"module_name":"财务系统","module_id":"B","nodes":[{"id":"B-1","text":"开始","position":"left"}]}]';
    var jsonString_right = '[{"module_name":"年度预算编制","module_id":"C","nodes":[{"id":"C-1","text":"结束","position":"right"}]},{"module_name":"营收编制","module_id":"D","nodes":[{"id":"D-1","text":"结束","position":"right"}]}]';
    // var nodeData_left = JSON.parse(jsonString_left);
    //[{"entity":null,"id":"934D62BD0F8249B09F29EC9FA051E390","code":"1","name":"CRM????","systemType":null,"databaseType":null,"hostName":null,"databaseaName":null,"userName":null,"password":null,"created":null,"modified":null},{"entity":null,"id":"81ABCD2890E2460B90A9B8A0ACE3FABD","code":null,"name":"CRM系统","systemType":null,"databaseType":null,"hostName":null,"databaseaName":null,"userName":null,"password":null,"created":null,"modified":null},{"entity":null,"id":"9AE1B07886E54F3DB0082D46392DE774","code":null,"name":"CRM系统","systemType":null,"databaseType":null,"hostName":null,"databaseaName":null,"userName":null,"password":null,"created":null,"modified":null},{"entity":null,"id":"E6D29376AC86455DBC3518D12F28C5B0","code":null,"name":"CRM系统","systemType":null,"databaseType":null,"hostName":null,"databaseaName":null,"userName":null,"password":null,"created":null,"modified":null}]
    var nodeData_right = data;
    this.setState({
        nodes_right: nodeData_right
    })
    //绘制右边点
    nodeData_right.map((node, index) => {
        this.setState({data_right: node, node_right: node.toModelList}, () => {
            this.initNodes(this.refs.nodes_right[index], 'right');
            // this.initEdges(nodeData.edges);
        });
    })
}

初始化连接锚点

initNodes = (node, position) => {
    this.jsp.setSuspendDrawing(true);
    if (position === "left") {
        DynamicAnchors.map(anchor => this.rjsp.addEndpoint(node, anEndpoint, {anchor: "Right"}));
    } else {
        DynamicAnchors_Right.map(anchor => this.rjsp.addEndpoint(node, anEndpoint, {anchor: "Left"}));
    }
    this.rjsp.setSuspendDrawing(false, true);
}

//自动连线

initEdges = (edges) => {
    this.rjsp.setSuspendDrawing(true);
    edges.map(edge => {
        this.jsp.connect(edge, Common);
    })
    this.jsp.setSuspendDrawing(false, true);
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容