G6实现可新增连线可拖拽的自定义拓扑图
容器:
<div id="container"></div>
图表实现:
init(){
insertCss(`
.g6-tooltip{
border-radius:6px;
font-size:14px;
color:#fff;
background-color:rgba(255,255,255,0.8);
padding:2px 8px;
text-align:center;
}
`)
//自定义节点
G6.registerNode('sql',{
drawShape(cfg,group){
const rect=group.addShape('rect',{
attrs:{
x:-60,
y:-20,
height:40,
width:120,
radius:10,
stroke:"#5B8FF9",
fill:"#C6E5FF",
lineWidth:2
},
name:"rect-shape"
})
//添加label
group.addShape('text',{
attrs:{
text:cfg.name,
x:0,
y:0,
fill:"#00287E",
fontSize:12,
textAlign:"center",
textBaseLine:"middle"
},
name:"text-shape"
})
return rect
}
},'single-node')
//自定义事件
G6.registerBehavior('click-add-edge',{
getEvents(){
return{
'node:click':'onClick',
'mousemove':'onMousemove',
'edge:click':'onEdgeClick'
}
},
//点击节点
onClick(ev){
const self=this
const node=ev.item
const graph=self.graph
const point={x:ev.x,y:ev.y}
const model=node.getModel()
if(self.addingEdge && self.edge){
graph.updateItem(self.edge,{
terget:model.id
})
self.edge=null
self.addingEdge=false
}else{
self.edge=graph.addItem('edge',{
source:model.id,
terget:model.id,
style:{
endArrow:true,
stroke:"rgba(208,224,247)",
lineWidth:2
}
})
self.addingEdge=true
}
},
onMousemove(ev){
const self=this
const point={x:ev.x,y:ev.y}
if(self.addingEdge && self.edge){
self.graph.updateItem(self.edge,{
target.point
})
}
},
onEdgeClick(ev){
const self=this
const currentEdge=ev.item
if(self.addingEdge && self.edge===currentEdge){
self.graph.removeItem(self.edge)
self.edge=null
self.addingEdge=false
}
}
})
//连线的菜单
const edgeMenu=new G6.Menu({
getContent(evt){
return`
<button style='border-radius:4px;
border:1px solid #1890ff;
background-color:#1890ff;
text-shadow:0 -1px 0 rgba(0,0,0,0.12);
box-shadow:0 2px 0 rgba(0,0,0,0.45);
width:50px;
height:30px;
cursor:pointer;
text-align:center;
color:#fff;'>删除</button>
`
},
//连线菜单事件
handleMenuClick:(terget,item)=>{
const model=item.getmodel()
let edge={
source:model.source,
target:model.target
}
let edgeArr=[]
edgeArr.push(edge)
let edges-this.graph.save().edges
edge.forEach((item,index)=>{
if(edge.source==item.source && edge.target==item.target){
edge.splice(index,1)
}
})
//重新给图表数据的连线赋值
this.sysdata.edges=edges
//假设节点有一栋,必须重新为nodes赋值 定位 渲染
this,sysdata.nodes=this.graph.save().nodes
this.graph.render()
},
offsetX:26,
offsetY:0,
itemTypes:['edge']
})
const container=document.getElementById("container")
const fittingString=(str,maxwidth,fontsize)=>{
let currrntWidth=0
let res=str
const pattern=new RegExp('[\u4E00-\u9FA5]+')
str.split("").forEach((letter,i)=>{
if(currentwidth>maxwidth) return;
if(pattern.test(letter)){
currentwidth += fontsize
}else{
currentwidth += G6.Util.getLetterWidth(letter,fontsize)
}
if(currentwidth > maxwidth){
res=`${str.substr(0,i)}\n${str.substr(i)}`
}
})
return res
}
//label字符串换行处理
this.sysdata.nodes.forEach(item=>{
item.name=fittingString(item.name,120,12)
})
//默认不适用任何布局
this.graph=new G6.Graph({
container:container,
width:this.localWidth,
height:this.localHeight,
plugins:[edgeMenu],
defaultNode:{
type:'sql'
},
animate:true,
modes:{
addEdge:['click-add-edge','click-select','drag-node','activate-relations','drag-canvas']
},
nodeStateStyles:{
selected:{
stroke:"rgba(208,224,247)",
lineWidth:2,
fill:"#e9f1f9"
}
},
defaultEdge:{
type:"line",
style:{
offset:45,
edgeArrow:true,
lineWidth:2,
stroke:"rgba(208,224,247)"
}
}
})
this.graph.setMode('addEge')
this.graph.data(this.sysdata)
//当edges为空时,添加布局,否则按照node的x y节点定位
if(this.sysdata.edges.length>0){
if(this.sysdata.nodes[0].x!==null){
console.log("有连线有定位")
}else{
console.log("有连线没定位 dagre定位")
this.graph.updataLayout({
type:"dagre",
ranksep:35
})
}
}
if(this.sysdata.edges.length==0){
if(this.sysdata.nodes[0].x!==null){
console.log("没连线有定位")
}else{
console.log("没连线没定位 grid布局")
if(this.sysdata.nodes.length==1){
this.graph.updataLayout({
type:"grid",
begin:[80,60]
})
}else{
this.graph.updataLayout({
type:"grid",
rows:5,
begin:[10,10],
width:1500-20
})
}
}
}
this.graph.render()
//计算拖拽后的节点
let dragstartX
let dragstartY
let dragX
let dragY
let count=0
let counts=0
let canvasY
this.graph.on('canvas:dragstart',e=>{
count++
dragstartX=e.canvasX
dragstartY=e.canvasY
})
this.graph.on('canvas:draged',e=>{
count++
if(count%2==1){
canvasY=e.canvasY
dragX=e.canvasX-dragstartX
dragY=e.canvasY-dragstartY
this.graph.save().nodes.forEach(item=>{
item.x=item.x+dragX
item.y=item.y+dragY
})
}
})
}