|
|
@ -1,7 +1,7 @@ |
|
|
|
<template> |
|
|
|
<div style="position: relative"> |
|
|
|
<!--width,height 画布的宽度,高度。 可以是百分比或像素,一般在dom元素上设置 --> |
|
|
|
<div id="network_id" class="network" style="height:80vh"></div> |
|
|
|
<div id="network_id" class="network" style="height: 80vh"></div> |
|
|
|
<!-- <div class="type-box" v-if="labelList && labelList.length">--> |
|
|
|
<!-- <el-radio-group v-model="type" @change="initRelation" style="width: 150px;">--> |
|
|
|
<!-- <el-radio label="" style="width: 120px;display: block;margin-right: 0px;margin: 5px 0px">--> |
|
|
@ -44,33 +44,33 @@ |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
<script> |
|
|
|
import Vis from "vis"; |
|
|
|
import Vis from 'vis'; |
|
|
|
|
|
|
|
export default { |
|
|
|
name: "vis-graph", |
|
|
|
name: 'vis-graph', |
|
|
|
props: { |
|
|
|
relationsView: { |
|
|
|
type: Object, |
|
|
|
default() { |
|
|
|
return {} |
|
|
|
return {}; |
|
|
|
} |
|
|
|
}, |
|
|
|
showTools: { |
|
|
|
type: Boolean, |
|
|
|
default() { |
|
|
|
return true |
|
|
|
return true; |
|
|
|
} |
|
|
|
}, |
|
|
|
labelList: { |
|
|
|
type: Array, |
|
|
|
default() { |
|
|
|
return [] |
|
|
|
return []; |
|
|
|
} |
|
|
|
}, |
|
|
|
colorMap: { |
|
|
|
type: Map, |
|
|
|
default() { |
|
|
|
return new Map() |
|
|
|
return new Map(); |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
@ -93,14 +93,14 @@ export default { |
|
|
|
edgesArray: [], |
|
|
|
options: {}, |
|
|
|
data: {}, |
|
|
|
isInit: false, |
|
|
|
isInit: false |
|
|
|
}; |
|
|
|
}, |
|
|
|
methods: { |
|
|
|
deleteRelation() { |
|
|
|
if (this.currentId) { |
|
|
|
this.$emit("deleteRelation", this.currentId); |
|
|
|
this.hideCircle() |
|
|
|
this.$emit('deleteRelation', this.currentId); |
|
|
|
this.hideCircle(); |
|
|
|
} |
|
|
|
}, |
|
|
|
deleteNode() { |
|
|
@ -111,34 +111,32 @@ export default { |
|
|
|
this.dataSet = new Set(); |
|
|
|
this.linkSet = new Set(); |
|
|
|
let _this = this; |
|
|
|
links.forEach(d => { |
|
|
|
links.forEach((d) => { |
|
|
|
if (!_this.linkSet.has(d.id)) { |
|
|
|
_this.edgesArray.push({ |
|
|
|
to: d.to, |
|
|
|
from: d.from, |
|
|
|
label: d.properties ? d.properties.name : "", |
|
|
|
'arrows': 'to', |
|
|
|
label: d.properties ? d.properties.name : '', |
|
|
|
arrows: 'to', |
|
|
|
id: d.id |
|
|
|
}) |
|
|
|
}); |
|
|
|
_this.linkSet.add(d.id); |
|
|
|
} |
|
|
|
|
|
|
|
}) |
|
|
|
datas.forEach(d => { |
|
|
|
}); |
|
|
|
datas.forEach((d) => { |
|
|
|
if (!_this.dataSet.has(d.id)) { |
|
|
|
_this.nodesArray.push({ |
|
|
|
id: d.id, |
|
|
|
labelId: d.labelId, |
|
|
|
label: d.name, color: {background: _this.colorMap.get(d.labelId)} |
|
|
|
label: d.name, |
|
|
|
color: { background: _this.colorMap.get(d.labelId) } |
|
|
|
}); |
|
|
|
_this.dataSet.add(d.id); |
|
|
|
} |
|
|
|
|
|
|
|
}) |
|
|
|
}); |
|
|
|
_this.init(); |
|
|
|
}, |
|
|
|
init() { |
|
|
|
debugger |
|
|
|
if (this.network) { |
|
|
|
this.network.destroy(); |
|
|
|
} |
|
|
@ -147,14 +145,14 @@ export default { |
|
|
|
_this.nodes = new Vis.DataSet(_this.nodesArray); |
|
|
|
//2.创建一个edges数组 |
|
|
|
_this.edges = new Vis.DataSet(_this.edgesArray); |
|
|
|
_this.container = document.getElementById("network_id"); |
|
|
|
_this.container = document.getElementById('network_id'); |
|
|
|
_this.data = { |
|
|
|
nodes: _this.nodes, |
|
|
|
edges: _this.edges |
|
|
|
}; |
|
|
|
_this.options = { |
|
|
|
autoResize: true, //网络将自动检测其容器的大小调整,并相应地重绘自身 |
|
|
|
locale: "cn", //语言设置:工具栏显示中文 |
|
|
|
locale: 'cn', //语言设置:工具栏显示中文 |
|
|
|
// configure:{ |
|
|
|
// showButton: true |
|
|
|
// }, |
|
|
@ -162,18 +160,18 @@ export default { |
|
|
|
locales: { |
|
|
|
cn: { |
|
|
|
//工具栏中文翻译 |
|
|
|
edit: "编辑", |
|
|
|
del: "删除当前节点或关系", |
|
|
|
back: "返回", |
|
|
|
addNode: "添加节点", |
|
|
|
addEdge: "添加连线", |
|
|
|
editNode: "编辑节点", |
|
|
|
editEdge: "编辑连线", |
|
|
|
addDescription: "点击空白处可添加节点", |
|
|
|
edgeDescription: "点击某个节点拖拽连线可连接另一个节点", |
|
|
|
editEdgeDescription: "可拖拽连线改变关系", |
|
|
|
createEdgeError: "无法将边连接到集群", |
|
|
|
deleteClusterError: "无法删除集群.", |
|
|
|
edit: '编辑', |
|
|
|
del: '删除当前节点或关系', |
|
|
|
back: '返回', |
|
|
|
addNode: '添加节点', |
|
|
|
addEdge: '添加连线', |
|
|
|
editNode: '编辑节点', |
|
|
|
editEdge: '编辑连线', |
|
|
|
addDescription: '点击空白处可添加节点', |
|
|
|
edgeDescription: '点击某个节点拖拽连线可连接另一个节点', |
|
|
|
editEdgeDescription: '可拖拽连线改变关系', |
|
|
|
createEdgeError: '无法将边连接到集群', |
|
|
|
deleteClusterError: '无法删除集群.', |
|
|
|
editClusterError: "无法编辑群集'" |
|
|
|
} |
|
|
|
}, |
|
|
@ -183,34 +181,34 @@ export default { |
|
|
|
myGroupId: {}, |
|
|
|
ws: { |
|
|
|
//系统定义的形状 dot等 这些官网都可以找到 |
|
|
|
shape: "dot", |
|
|
|
color: "white" |
|
|
|
shape: 'dot', |
|
|
|
color: 'white' |
|
|
|
} |
|
|
|
}, |
|
|
|
// 设置节点样式 |
|
|
|
nodes: { |
|
|
|
//节点的外观。为circle时label显示在节点内,为dot时label显示在节点下方 |
|
|
|
shape: "dot", |
|
|
|
shape: 'dot', |
|
|
|
size: 50, |
|
|
|
fixed: false, |
|
|
|
font: { |
|
|
|
//字体配置 |
|
|
|
size: 24, |
|
|
|
size: 24 |
|
|
|
//文字向下移动的位置 |
|
|
|
// vadjust:-75 |
|
|
|
}, |
|
|
|
color: { |
|
|
|
border: "#2B7CE9", //节点边框颜色 |
|
|
|
background: "#97C2FC", //节点背景颜色 |
|
|
|
border: '#2B7CE9', //节点边框颜色 |
|
|
|
background: '#97C2FC', //节点背景颜色 |
|
|
|
highlight: { |
|
|
|
//节点选中时状态颜色 |
|
|
|
border: "#2B7CE9", |
|
|
|
background: "#D2E5FF" |
|
|
|
border: '#2B7CE9', |
|
|
|
background: '#D2E5FF' |
|
|
|
}, |
|
|
|
hover: { |
|
|
|
//节点鼠标滑过时状态颜色 |
|
|
|
border: "#2B7CE9", |
|
|
|
background: "#D2E5FF" |
|
|
|
border: '#2B7CE9', |
|
|
|
background: '#D2E5FF' |
|
|
|
} |
|
|
|
}, |
|
|
|
mass: 5, |
|
|
@ -224,10 +222,10 @@ export default { |
|
|
|
width: 1, |
|
|
|
length: 260, |
|
|
|
color: { |
|
|
|
color: "#848484", |
|
|
|
highlight: "#848484", |
|
|
|
hover: "#848484", |
|
|
|
inherit: "from", |
|
|
|
color: '#848484', |
|
|
|
highlight: '#848484', |
|
|
|
hover: '#848484', |
|
|
|
inherit: 'from', |
|
|
|
opacity: 1.0 |
|
|
|
}, |
|
|
|
shadow: true, |
|
|
@ -235,7 +233,7 @@ export default { |
|
|
|
//设置两个节点之前的连线的状态 |
|
|
|
enabled: true //默认是true,设置为false之后,两个节点之前的连线始终为直线,不会出现贝塞尔曲线 |
|
|
|
}, |
|
|
|
arrows: {to: true} //箭头指向to |
|
|
|
arrows: { to: true } //箭头指向to |
|
|
|
}, |
|
|
|
//计算节点之前斥力,进行自动排列的属性 |
|
|
|
physics: { |
|
|
@ -272,11 +270,7 @@ export default { |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
_this.network = new Vis.Network( |
|
|
|
_this.container, |
|
|
|
_this.data, |
|
|
|
_this.options |
|
|
|
); |
|
|
|
_this.network = new Vis.Network(_this.container, _this.data, _this.options); |
|
|
|
}, |
|
|
|
|
|
|
|
resetAllNodes() { |
|
|
@ -290,11 +284,7 @@ export default { |
|
|
|
edges: _this.edges |
|
|
|
}; |
|
|
|
// network是一种用于将包含点和线的网络和网络之间的可视化展示 |
|
|
|
_this.network = new Vis.Network( |
|
|
|
_this.container, |
|
|
|
_this.data, |
|
|
|
_this.options |
|
|
|
); |
|
|
|
_this.network = new Vis.Network(_this.container, _this.data, _this.options); |
|
|
|
}, |
|
|
|
resetAllNodesStabilize() { |
|
|
|
let _this = this; |
|
|
@ -303,65 +293,61 @@ export default { |
|
|
|
}, |
|
|
|
parentDeleteRelation(id) { |
|
|
|
console.log(id); |
|
|
|
this.edgesArray = this.edgesArray.filter(row => row.id != id) |
|
|
|
this.edgesArray = this.edgesArray.filter((row) => row.id != id); |
|
|
|
console.log(this.data.edges); |
|
|
|
this.data.edges.remove(id) |
|
|
|
this.data.edges.remove(id); |
|
|
|
console.log(this.data.edges); |
|
|
|
this.linkSet.delete(id) |
|
|
|
this.linkSet.delete(id); |
|
|
|
}, |
|
|
|
addDatas(datas) { |
|
|
|
let _this = this; |
|
|
|
if (datas.nodes && datas.nodes.length > 0) { |
|
|
|
datas.links.forEach(d => { |
|
|
|
datas.links.forEach((d) => { |
|
|
|
if (!_this.linkSet.has(d.id)) { |
|
|
|
_this.linkSet.add(d.id); |
|
|
|
let link = { |
|
|
|
to: d.to, |
|
|
|
from: d.from, |
|
|
|
label: d.properties ? d.properties.name : "", |
|
|
|
'arrows': 'to', |
|
|
|
label: d.properties ? d.properties.name : '', |
|
|
|
arrows: 'to', |
|
|
|
id: d.id |
|
|
|
}; |
|
|
|
_this.edgesArray.push(link) |
|
|
|
_this.data.edges.add(link) |
|
|
|
|
|
|
|
_this.edgesArray.push(link); |
|
|
|
_this.data.edges.add(link); |
|
|
|
} |
|
|
|
|
|
|
|
}) |
|
|
|
datas.nodes.forEach(d => { |
|
|
|
}); |
|
|
|
datas.nodes.forEach((d) => { |
|
|
|
if (!_this.dataSet.has(d.id)) { |
|
|
|
_this.dataSet.add(d.id); |
|
|
|
let node = { |
|
|
|
id: d.id, |
|
|
|
labelId: d.labelId, |
|
|
|
label: d.name, color: {background: _this.colorMap.get(d.labelId)} |
|
|
|
} |
|
|
|
label: d.name, |
|
|
|
color: { background: _this.colorMap.get(d.labelId) } |
|
|
|
}; |
|
|
|
_this.nodesArray.push(node); |
|
|
|
|
|
|
|
_this.data.nodes.add(node); |
|
|
|
} |
|
|
|
|
|
|
|
}) |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
}, |
|
|
|
addOneNode() { |
|
|
|
if (this.currentId) { |
|
|
|
this.$emit("nextNode", this.currentId); |
|
|
|
this.$emit('nextNode', this.currentId); |
|
|
|
} |
|
|
|
}, |
|
|
|
addRelation() { |
|
|
|
if (this.currentId) { |
|
|
|
this.$emit("addNode", this.currentId); |
|
|
|
this.$emit('addNode', this.currentId); |
|
|
|
} |
|
|
|
}, |
|
|
|
editNode() { |
|
|
|
this.$emit("updateNode", this.currentId) |
|
|
|
this.hideCircle() |
|
|
|
this.$emit('updateNode', this.currentId); |
|
|
|
this.hideCircle(); |
|
|
|
}, |
|
|
|
toDetail() { |
|
|
|
this.$emit("toDetail", this.currentId) |
|
|
|
this.$emit('toDetail', this.currentId); |
|
|
|
}, |
|
|
|
// 设置环形位置 |
|
|
|
setCirclePosition() { |
|
|
@ -369,14 +355,16 @@ export default { |
|
|
|
// this.domPosi["y"] + 10, |
|
|
|
// this.scale + 0.4 |
|
|
|
|
|
|
|
let circle = document.getElementById("circle-option"); |
|
|
|
circle.style = `left: ${this.domPosi["x"] - 50}px; top: ${this.domPosi["y"] - 50}px;transform:scale(${this.scale * 2.5});display:block;`; |
|
|
|
let circle = document.getElementById('circle-option'); |
|
|
|
circle.style = `left: ${this.domPosi['x'] - 50}px; top: ${this.domPosi['y'] - 50}px;transform:scale(${ |
|
|
|
this.scale * 2.5 |
|
|
|
});display:block;`; |
|
|
|
}, |
|
|
|
// 隐藏圆环选项 |
|
|
|
hideCircle() { |
|
|
|
let circle = document.getElementById("circle-option"); |
|
|
|
let circle = document.getElementById('circle-option'); |
|
|
|
circle.style = `display:none;`; |
|
|
|
}, |
|
|
|
} |
|
|
|
}, |
|
|
|
watch: { |
|
|
|
domPosi(newval) { |
|
|
@ -395,15 +383,15 @@ export default { |
|
|
|
} |
|
|
|
}, |
|
|
|
deep: true, |
|
|
|
immediate: true, |
|
|
|
immediate: true |
|
|
|
}, |
|
|
|
labelList: { |
|
|
|
handler(newVal) { |
|
|
|
this.labelList = newVal; |
|
|
|
}, |
|
|
|
deep: true, |
|
|
|
immediate: true, |
|
|
|
}, |
|
|
|
immediate: true |
|
|
|
} |
|
|
|
}, |
|
|
|
mounted() { |
|
|
|
//获取类别的颜色 |
|
|
@ -411,38 +399,38 @@ export default { |
|
|
|
|
|
|
|
this.init(); |
|
|
|
|
|
|
|
this.network.on("stabilized", param => { |
|
|
|
this.network.on('stabilized', (param) => { |
|
|
|
// console.log("图谱渲染完成", param) |
|
|
|
}) |
|
|
|
this.network.on("zoom", param => { |
|
|
|
}); |
|
|
|
this.network.on('zoom', (param) => { |
|
|
|
if (this.currentId) { |
|
|
|
let circle = document.getElementById("circle-option"); |
|
|
|
if ("none" !== circle.style.display) { |
|
|
|
let circle = document.getElementById('circle-option'); |
|
|
|
if ('none' !== circle.style.display) { |
|
|
|
this.scale = param.scale; |
|
|
|
let p = this.network.getPositions(this.currentId); |
|
|
|
// this.scale = _this.network.getScale(); |
|
|
|
this.domPosi = this.network.canvasToDOM({ |
|
|
|
x: p[this.currentId]["x"], |
|
|
|
y: p[this.currentId]["y"], |
|
|
|
x: p[this.currentId]['x'], |
|
|
|
y: p[this.currentId]['y'] |
|
|
|
}); |
|
|
|
} |
|
|
|
} else { |
|
|
|
this.hideCircle(); |
|
|
|
} |
|
|
|
}) |
|
|
|
this.network.on("dragStart", param => { |
|
|
|
}); |
|
|
|
this.network.on('dragStart', (param) => { |
|
|
|
// this.currentId = param.nodes[0] |
|
|
|
this.isInit = false; |
|
|
|
this.hideCircle(); |
|
|
|
}) |
|
|
|
this.network.on("dragEnd", param => { |
|
|
|
}); |
|
|
|
this.network.on('dragEnd', (param) => { |
|
|
|
if (param.nodes && param.nodes.length > 0) { |
|
|
|
this.network.clustering.updateClusteredNode(param.nodes[0], {physics: false}); |
|
|
|
this.network.clustering.updateClusteredNode(param.nodes[0], { physics: false }); |
|
|
|
} |
|
|
|
this.hideCircle(); |
|
|
|
}) |
|
|
|
}); |
|
|
|
// 点击事件 |
|
|
|
this.network.on("click", params => { |
|
|
|
this.network.on('click', (params) => { |
|
|
|
if (!this.showTools) { |
|
|
|
return; |
|
|
|
} |
|
|
@ -450,32 +438,32 @@ export default { |
|
|
|
let _this = this; |
|
|
|
if (params.nodes && params.nodes.length > 0) { |
|
|
|
_this.currentId = params.nodes[0]; |
|
|
|
_this.network.clustering.updateClusteredNode(_this.currentId, {physics: false}); |
|
|
|
if (_this.currentId) { //节点点击 |
|
|
|
_this.network.clustering.updateClusteredNode(_this.currentId, { physics: false }); |
|
|
|
if (_this.currentId) { |
|
|
|
//节点点击 |
|
|
|
// _this.network. |
|
|
|
let p = _this.network.getPositions(_this.currentId); |
|
|
|
_this.scale = _this.network.getScale(); |
|
|
|
_this.domPosi = _this.network.canvasToDOM({ |
|
|
|
x: p[_this.currentId]["x"], |
|
|
|
y: p[_this.currentId]["y"], |
|
|
|
x: p[_this.currentId]['x'], |
|
|
|
y: p[_this.currentId]['y'] |
|
|
|
}); |
|
|
|
// 设置环形位置; |
|
|
|
_this.setCirclePosition(); |
|
|
|
$(".custom-menu").hide(); |
|
|
|
$('.custom-menu').hide(); |
|
|
|
} else { |
|
|
|
this.hideCircle(); |
|
|
|
} |
|
|
|
} else if (params.edges && params.edges.length) { |
|
|
|
} else { |
|
|
|
this.hideCircle(); |
|
|
|
$(".custom-menu").hide(); |
|
|
|
$('.custom-menu').hide(); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
}; |
|
|
|
</script> |
|
|
|
<style lang="scss"> |
|
|
|
|
|
|
|
.circle-option { |
|
|
|
position: absolute; |
|
|
|
left: 0px; |
|
|
@ -560,12 +548,13 @@ export default { |
|
|
|
} |
|
|
|
|
|
|
|
.custom-menu div a { |
|
|
|
font-family: "微软雅黑"; |
|
|
|
font-family: '微软雅黑'; |
|
|
|
font-size: 14px; |
|
|
|
color: rgb(255, 255, 255); |
|
|
|
} |
|
|
|
|
|
|
|
.custom-menu div a:HOVER, .custom-menu div a:ACTIVE { |
|
|
|
.custom-menu div a:hover, |
|
|
|
.custom-menu div a:active { |
|
|
|
cursor: pointer; |
|
|
|
color: orange; |
|
|
|
} |
|
|
|