可新增连线的拓扑图实现

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
			})
		}
	})

}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值