vue2 + jsPlumb

vue+jsplumb实现连线绘图,供大家参考,具体内容如下

jsPlumb是一个比较强大的绘图组件,它提供了一种方法,主要用于连接网页上的元素。在现代浏览器中,它使用SVG或者Canvas技术,而对于IE8以下(含IE8)的浏览器,则使用VML技术。

效果如图

1.安装

npm install jsplumb --save

2.main.js 引入

import jsPlumb from 'jsplumb'

Vue.prototype.$jsPlumb = jsPlumb.jsPlumb

3.封装组件 linkDataJsPlumb.vue

<template>
    <div>
        <div id="container" class='clear-float'>
            <div class="left">
                <ul>
                    <div class='titleContend clear-float'>
                        <div class='float firstField'>源表字段</div>
                        <div class='float secondField'>类型</div>
                        <div class='float thirdField'>描述</div>
                    </div>
                    <li v-for="(item,index) in leftList" :key="'left' + index" :id="item.nodeId" name="source">
                        <div class='titleContend clear-float'>
                            <div class='float firstField'>{{item.name}}</div>
                            <div class='float secondField'>{{item.name}}</div>
                            <div class='float thirdField'>{{item.name}}</div>
                        </div>
                    </li>
                </ul>
            </div>
            <div class="right">
                <ul>
                    <div class='titleContend clear-float'>
                        <div class='float firstField'>识别字段</div>
                    </div>
                    <li v-for="(item,index) in rightList" :key="'right' + index" :id="item.nodeId" name="target">
                        <div class='titleContend clear-float'>
                            <div class='float firstField'>{{item.name}}</div>
                        </div>
                    </li>
                </ul>
            </div>
        </div>
    </div>
</template>

<script>
export default {
    name: 'linkElementModal',
    props: {
        // 左侧数据 [{ name: 'xxx_left_1', nodeId: 'left_1' }]
        leftList: {
            type: Array,
            default: () => {
                return [];
            }
        },
        // 右侧数据 [{ name: 'xxx_right_1', nodeId: 'right_1' }]
        rightList: {
            type: Array,
            default: () => {
                return [];
            }
        },
        // 默认数据 [{left: 'left_1', right: 'right_1'}]
        value: {
            type: Array,
            default: () => {
                return [];
            }
        }
    },
    data () {
        return {
            jsPlumb: null // 缓存实例化的jsplumb对象
        };
    },
    mounted () {
        this.showPlumb();
    },
    methods: {
        showPlumb () {
            this.jsPlumb = this.$jsPlumb.getInstance({
                Container: 'container', // 选择器id
                EndpointStyle: { radius: 0.11, fill: '#999' }, // 端点样式
                PaintStyle: { stroke: '#999', strokeWidth: 2 }, // 绘画样式,默认8px线宽  #456
                HoverPaintStyle: { stroke: '#994B0A', strokeWidth: 3 }, // 默认悬停样式  默认为null
                ConnectionOverlays: [ // 此处可以设置所有箭头的样式
                    ['Arrow', { // 设置参数可以参考中文文档
                        location: 1,
                        width: 10,
                        length: 6,
                        paintStyle: {
                            stroke: '#999',
                            fill: '#999'
                        }
                    }]
                ],
                Connector: ['Straight'], // 要使用的默认连接器的类型:直线,折线,曲线等
                DrapOptions: { cursor: 'crosshair', zIndex: 2000 }
            });

            this.jsPlumb.batch(() => {
                for (let i = 0; i < this.leftList.length; i++) {
                    this.initLeaf(this.leftList[i].nodeId, 'source');
                }
                for (let j = 0; j < this.rightList.length; j++) {
                    this.initLeaf(this.rightList[j].nodeId, 'target');
                }
            });

            this.setjsPlumb(true, true);

            // 点击连线
            this.jsPlumb.bind('click', (conn, originalEvent) => {
                this.value.forEach((item, index) => {
                    if (item.left == conn.sourceId) {
                        this.value.splice(index, 1);
                    }
                });
                this.jsPlumb.deleteConnection(conn);
            });

            // 连线时触发
            this.jsPlumb.bind('connection', (conn, originalEvent) => {
                let obg = {
                    left: conn.sourceId,
                    right: conn.targetId
                };
                this.value.push(obg);
            });

            // 右键触发
            this.jsPlumb.bind('contextmenu', (conn, originalEvent) => {
                console.log(conn, originalEvent);
            });
        },
        //  初始化规则使其可以连线、拖拽
        initLeaf (id, type) {
            const ins = this.jsPlumb;
            const elem = document.getElementById(id);
            if (type === 'source') {
                ins.makeSource(elem, {
                    anchor: [1, 0.5, 0, 0], // 左 上 右 下
                    allowLoopback: false, // 允许回连
                    maxConnections: 1 // 最大连接数(-1表示不限制)
                });
            } else {
                ins.makeTarget(elem, {
                    anchor: [0, 0.5, 0, 0],
                    allowLoopback: false,
                    maxConnections: 1
                });
            }
        },
        setjsPlumb (sourceFlag, targetFlag) {
            const source = document.getElementsByName('source');
            const target = document.getElementsByName('target');
            this.jsPlumb.setSourceEnabled(source, sourceFlag);
            this.jsPlumb.setTargetEnabled(target, targetFlag);
            this.jsPlumb.setDraggable(source, false); // 是否支持拖拽
            this.jsPlumb.setDraggable(target, false); // 是否支持拖拽
            // 是否含有默认数据
            if (this.value.length > 0) {
                this.initConnect();
            }
        },
        // 默认链接
        initConnect () {
            const jsplumbConnectOptions = {
                isSource: true,
                isTarget: true,
                // 动态锚点、提供了4个方向 Continuous、AutoDefault
                anchor: 'Continuous'
            };
            this.jsPlumb.deleteEveryConnection();
            for (var i = 0; i < this.value.length; i++) {
                let line = this.value[i];
                this.jsPlumb.connect({
                    source: line.left,
                    target: line.right
                }, jsplumbConnectOptions);
            }
        }
    }
};
</script>

<style>
#container {
    width: 500px;
    padding: 20px;
    position: relative; /*一定加上这句,否则连线位置发生错乱*/
}

.left {
    float: left;
    width: auto;
}
.right {
    float: right;
    width: auto;
}

.left li,
.right li {
    list-style: none;
    width: auto;
}
</style>
<style lang='scss' scoped>
.titleContend {
    width: auto;
    height: 30px;
    line-height: 30px;
    border-bottom: 1px solid #cccccc;
    .float {
        float: left;
    }
    .firstField {
        width: 100px;
    }
    .secondField {
        width: 100px;
    }
    .thirdField {
        width: 80px;
    }
}
</style>

4.使用组件 

<linkDataJsPlumb v-model='defaultList' :leftList='leftList' :rightList='rightList'/>

import linkDataJsPlumb from './components/linkDataJsPlumb';

// 左侧数据
leftList: [
    { name: 'xxx_left_1', nodeId: 'left_1' },
    { name: 'xxx_left_2', nodeId: 'left_2' },
    { name: 'xxx_left_3', nodeId: 'left_3' },
    { name: 'xxx_left_4', nodeId: 'left_4' }
],
rightList: [
    { name: 'xxx_right_1', nodeId: 'right_1' },
    { name: 'xxx_right_2', nodeId: 'right_2' },
    { name: 'xxx_right_3', nodeId: 'right_3' },
    { name: 'xxx_right_4', nodeId: 'right_4' }
],
// 默认值
defaultList: [
    {left: 'left_1', right: 'right_2'},
    {left: 'left_2', right: 'right_3'},
    {left: 'left_3', right: 'right_1'}
]

博客前端开发 | NoteZ_技术博客

中文mirrors / wangduanduan / jsplumb-chinese-tutorial · GitCode

jsPlumb的初始化

使用jsPlumb进行实例化的同时可以传入相关属性的设置。

this.jsp = jsPlumb.getInstance({
    Anchor: ["Right", "Left"], 
//锚点位置,如left,top,bottom等;对任何没有声明描点的Endpoint设置锚点,
//用于source或target节点
//设置为数组可以指定锚点的位置
    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,
            cssClass: "aLabel", //hover时label的样式名
            events: {
                click:info=>{
                    console.log(info);
                }
            },
            visible: true
        }]
    ],
    Connector: "Straight", 
//连线的类型,有直线(Sright),有流程图(Flowchart)、贝塞尔曲线(Bezier),State machine(状态机)
    Container: "module",
 //父级元素id;假如页面元素所在上层不同,最外层父级一定要设置
    DoNotThrowErrors: false,
 //如果请求不存在的Anchor、Endpoint或Connector,是否抛异常
    DragOptions : { },//用于配置拖拽元素的参数
    DropOptions : { },//用于配置元素的drop行为的参数
    Endpoint: "Dot", //端点(锚点)的样式声明
    Endpoints: [null, null],
 //用jsPlumb.connect创建连接时,source端点和target端点的样式设置
    EndpointOverlays: [], //端点的叠加物
    EndpointStyle: {fill: 'transparent', stroke: '#1565C0', radius: 4, strokeWidth: 1}, //端点的默认样式
    EndpointStyles: [null, null], //连线的source和target端点的样式
    EndpointHoverStyle: {fill: '#1565C0', stroke: '#1565C0', radius: 4, strokeWidth: 1}, //端点hover时的样式
    EndpointHoverStyles: [null, null], //连线的source和target端点hover时的样式
    HoverPaintStyle: {stroke: '#1565C0', strokeWidth: 3}, //连线hover时的样式
    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,
})

jsPlumb的相关方法

  • 添加连线

let params={source: info.sourceId, target: info.targetId};
let setting=为自定义的jsPlumb设置,也可以不传入
this.jsp.connect(params,setting);
  • 删除连线

this.jsp.removeAllEndpoints(node)这个方法删除指定的节点和连线,传入的node为节点元素
this.jsp.deleteEveryConnection();这个方法删除所有连线,不需要传入参数      
this.jsp.deleteEveryEndpoint();这个方法删除所有节点,不需要传入参数
this.jsp.deleteConnectionsForElement("A-1",{});删除制定的连线,传入节点ID
  • 重绘连线

this.jsp.repaintEverything()//重绘连线
this.jsp.setSuspendDrawing(true);
this.jsp.setSuspendDrawing(false,true);
这里第二个参数的true,会使整个jsPlumb立即重绘。

注意:

 因为jsPlumb 是通过DOM进行工作的,所以我们需要把jsPlumb初始化 放在mounted声明,
如果是在子组件中完成,需要保证子组件渲染完成才可进行处理,可以放在进行初始化this.$nextTick(()=>{  } )

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值