基于jtopo实现拖拽和连线




</pre>上代码:<p></p><p></p><p>jtopoDemo.html</p><p></p><pre name="code" class="html"><!DOCTYPE html>
<html>
  <head>
    <title>拓扑</title>
	
    <meta name="keywords" content="keyword1,keyword2,keyword3">
    <meta name="description" content="this is my page">
    <meta name="content-type" content="text/html; charset=UTF-8">
    <!-- 配置自己的路径  -->
    <script type="text/javascript" src="../../view/common/js/jquery-2.2.3.min.js"></script>
    <script type="text/javascript" src="../../view/common/js/jtopo-0.4.8-min.js"></script>
  	
  	
  	<script type="text/javascript" src="js/conf.js"></script>
  	<script type="text/javascript" src="js/mytopo.js"></script>
  	<script type="text/javascript" src="js/toolbar.js"></script>
  	<script type="text/javascript" src="js/tooldrag.js"></script>
  	<link rel="stylesheet" type="text/css" href="css/base.css">
  </head>
  
  <body>
     拓扑测试<br>
	<div id="content" style="width:900px;position:relative;">
		<div style="width: 900px;height: 40px;border: 1px solid rgb(68, 68, 68);position:absolute; top:35px;">
			<!--原始节点  -->
			<canvas id='exchanger_icon' width='100' height='40' 
              draggable="true" οndragstart="drag(event)">
                                        当前浏览器无法使用canvas标签,请更换新版本浏览器
             </canvas>
             <canvas id='server_icon' width='100' height='40' 
              draggable="true" οndragstart="drag(event)">
                                        当前浏览器无法使用canvas标签,请更换新版本浏览器
             </canvas>
		</div>
		<div id="dst" οndrοp="drop(event)" οndragοver="allowDrop(event)">
             <canvas width="900px" height="550px" id="canvas" 
             style="border: 1px solid rgb(68, 68, 68);"  >
                                      当前浏览器无法使用canvas标签,请更换新版本浏览器</canvas>                    
        </div>	
		
		
	</div>
	<img alt="" src="" id="img" >
</body>
</html>



conf.js

var islink=false;  //是否默认连线

var nodelist=new Array(); 



mytopo.js

 $(document).ready(function(){
	
	 var canvas = document.getElementById('canvas'); 
	 stage = new JTopo.Stage(canvas); // 创建一个舞台对象
	 scene = new JTopo.Scene(stage); // 创建一个场景对象
	
	//显示工具栏
	showJTopoToobar(stage);

    stage.addEventListener("mouseover", function(event){
    	
    	 console.log("鼠标进入");
    	 
    	 
     });
     stage.addEventListener("mousedrag", function(event){
    	 
    	 console.log("拖拽");
    	 
     });
     
     stage.addEventListener("mouseup", function(event){
    	 
    	 if(event.button == 2){
    		 console.log ('松开右键');	
    		 
		 }else if(event.button == 1){
				console.log =('松开中键');					
		 }else if(event.button == 0){
			console.log ( '松开左键');	
		 }
    	 
     });
     
     stage.addEventListener("mousemove", function(event){
    	 
     });
     
 });
 
 
 //打印鼠标指针坐标
 function writeMessage (oGetMousePos,message) {
	 var oContext=oGetMousePos.getContext("2d");
     oContext.clearRect(0, 0, oGetMousePos.width, oGetMousePos.height);
     oContext.font = "20pt Microsoft JhengHei";
     oContext.fillStyle = "tomato";
     oContext.fillText(message, 10, 60);
 };
 
 
 
 
 //获取画布中鼠标的位置
 function getMousePos(canvas, evt, scene) { 
	   var rect = canvas.getBoundingClientRect(); 
	   
	   return { 
		   x: evt.clientX - rect.left * (canvas.width / rect.width)- (scene?scene.translateX:0),
		   y: evt.clientY - rect.top * (canvas.height / rect.height)- (scene?scene.translateY:0)
	   }
}
 

//绘制节点
 function draw(ev,data){
 	var mousePos = getMousePos(stage.canvas,ev,scene);
 	var message = "x:" + mousePos.x + ",y:" + mousePos.y;
 	console.log(message,data);
 	addNode(data,mousePos);
 	
 	//防止创建节点后连线
 	nodelist=[];
 }
 
 //添加节点
 function addNode(name,mousePos){
		var node = new JTopo.Node(name);
		node.setLocation(mousePos.x,mousePos.y);
	    node.setImage("img/"+name+".png"); 
	    node.shadow = "true";
	    //node.showSelected = "false";
	    scene.add(node);
	    node.dbclick(function(ev){
	    	console.log(node.text+"被点双击了");
	    });
	    node.mouseup(function(ev){
	    	console.log(node.text+"鼠标离开");
	    	
	    	//是否连线
	    	if(islink){
	    		nodelist.push(node);
	    		if(nodelist.length>=2&&nodelist[nodelist.length-1]!=nodelist[nodelist.length-2]){
	    			console.log("11");
	    			linkNode(nodelist[nodelist.length-1],nodelist[nodelist.length-2]);
	    			nodelist=[];
	    			
	    		}
	    	}
	    });
}
 

//增加连线
 function linkNode(nodeFrom,nodeTo){
	 var link = new JTopo.Link(nodeFrom, nodeTo); 
	 link.click(function(ev){
		 console.log("点击了连线");
	 });
	 link.click(function(ev){
		 console.log("点击了连线");
	 });
	 scene.add(link);
 }
 
 //删除节点或者连线
 function delNode(node){
	 scene.remove(node);
 }

toolbar.js  //jtopo的

// 页面工具栏
function showJTopoToobar(stage){
	var toobarDiv = $('<div class="jtopo_toolbar">').html(''
		+'<input type="radio" name="modeRadio" value="normal" checked id="r1"/>'
		+'<label for="r1"> 默认</label>'
		+' <input type="radio" name="modeRadio" value="select" id="r2"/><label for="r2"> 框选</label>'
		//+' <input type="radio" name="modeRadio" value="edit" id="r4"/><label for="r4"> 连线</label>'
		+'  <input type="button" id="centerButton" value="居中显示"/>'
		+'<input type="button" id="fullScreenButton" value="全屏显示"/>'
		+'<input type="button" id="zoomOutButton" value=" 放 大 " />'
		+'<input type="button" id="zoomInButton" value=" 缩 小 " />'
		+'  <input type="checkbox" id="linkCheckbox"/><label for="linkCheckbox">连接节点</label>'
		+'  <input type="checkbox" id="zoomCheckbox"/><label for="zoomCheckbox">鼠标缩放</label>'
		+'  <input type="checkbox" id="eyeCheckbox"/><label for="eyeCheckbox">鹰眼</label>'
		+'  <input type="text" id="findText" style="width: 100px;" value="" οnkeydοwn="enterPressHandler(event)">'
		+ '<input type="button" id="findButton" value=" 查 询 ">' 
		+ '  <input type="button" id="cloneButton" value="选中克隆">'
		+'  <input type="button" id="exportButton" value="导出PNG">'
		+ '  <input type="button" id="printButton" value="导出PDF">');	
		
	$('#content').prepend(toobarDiv);

	// 工具栏按钮处理
	$("input[name='modeRadio']").click(function(){			
		stage.mode = $("input[name='modeRadio']:checked").val();
	});

	$('#centerButton').click(function(){
		stage.centerAndZoom(); //缩放并居中显示
	});
	$('#zoomOutButton').click(function(){
		stage.zoomOut();
	});
	$('#zoomInButton').click(function(){
		stage.zoomIn();
	});
	$('#cloneButton').click(function(){
		var img = document.getElementById('img'); 
		var c=stage.eagleEye.getImage();
		img.src =c;  
	});
	$('#exportButton').click(function() {
	    stage.saveImageInfo();
	});
	$('#printButton').click(function() {
	    stage.saveImageInfo();
	});
	$('#linkCheckbox').click(function(){
		islink=$('#linkCheckbox').is(':checked');
	});
	$('#zoomCheckbox').click(function(){
		if($('#zoomCheckbox').is(':checked')){
			stage.wheelZoom = 1.2; // 设置鼠标缩放比例
		}else{
			stage.wheelZoom = null; // 取消鼠标缩放比例
		}
	});
	$('#eyeCheckbox').click(function(){
		if($('#eyeCheckbox').is(':checked')){
			stage.eagleEye.visible = true;
		}else{
			stage.eagleEye.visible = false;
		}
	});
	$('#fullScreenButton').click(function(){
		runPrefixMethod(stage.canvas, "RequestFullScreen")
	});

	window.enterPressHandler = function (event){
		if(event.keyCode == 13 || event.which == 13){
			$('#findButton').click();
		}
	};
	
	// 查询
	$('#findButton').click(function(){
		var text = $('#findText').val().trim();
		//var nodes = stage.find('node[text="'+text+'"]');
		var scene = stage.childs[0];
		var nodes = scene.childs.filter(function(e){ 
			return e instanceof JTopo.Node; 
		});
		nodes = nodes.filter(function(e){
			if(e.text == null) return false;
			return e.text.indexOf(text) != -1;
		});
		
		if(nodes.length > 0){
			var node = nodes[0];
			node.selected = true;
			var location = node.getCenterLocation();
			// 查询到的节点居中显示
			stage.setCenter(location.x, location.y);
			
			function nodeFlash(node, n){
				if(n == 0) {
					node.selected = false;
					return;
				};
				node.selected = !node.selected;
				setTimeout(function(){
					nodeFlash(node, n-1);
				}, 300);
			}
			
			// 闪烁几下
			nodeFlash(node, 6);
		}
	});
}

var runPrefixMethod = function(element, method) {
	var usablePrefixMethod;
	["webkit", "moz", "ms", "o", ""].forEach(function(prefix) {
		if (usablePrefixMethod) return;
		if (prefix === "") {
			// 无前缀,方法首字母小写
			method = method.slice(0,1).toLowerCase() + method.slice(1);
		}
		var typePrefixMethod = typeof element[prefix + method];
		if (typePrefixMethod + "" !== "undefined") {
			if (typePrefixMethod === "function") {
				usablePrefixMethod = element[prefix + method]();
			} else {
				usablePrefixMethod = element[prefix + method];
			}
		}
	}
);

return usablePrefixMethod;
};
/*
runPrefixMethod(this, "RequestFullScreen");
if (typeof window.screenX === "number") {
var eleFull = canvas;
eleFull.addEventListener("click", function() {
	if (runPrefixMethod(document, "FullScreen") || runPrefixMethod(document, "IsFullScreen")) {
		runPrefixMethod(document, "CancelFullScreen");
		this.title = this.title.replace("退出", "");
	} else if (runPrefixMethod(this, "RequestFullScreen")) {
		this.title = this.title.replace("点击", "点击退出");
	}
});
} else {
alert("浏览器不支持");
}*/

tooldrag.js

//拖拽节点的初始化,以及拖拽拖拽操作

$(document).ready(function(){
	 init("server_icon");    //云主机
	 init("exchanger_icon"); //交换机
});

function init(id){
	var canvasSrc = document.getElementById(id);
	var contextSrc = canvasSrc.getContext('2d');
	var image = new Image();
	 image.src="img/"+id+".png";
	 image.οnlοad=function(){
	         contextSrc.drawImage(image,0,0);
	 }
}



function allowDrop(ev){
        ev.preventDefault();
}

//拖拽开始
function drag(ev){
        ev.dataTransfer.setData("Text", ev.target.id);  
}

//拖拽结束
function drop(ev){
        //ev.preventDefault();
       var data = ev.dataTransfer.getData("Text");
        //ev.target.appendChild(document.getElementById(data));
        draw(ev,data);
}



文件格式:





  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
以下是一个用 Vue 实现拖拽产生连线的示例代码: ```html <template> <div class="container"> <div class="box" v-for="(item, index) in boxes" :key="index" :style="{ top: item.top + 'px', left: item.left + 'px' }" @mousedown="startDrag($event, item)"> <span>{{ index }}</span> </div> <svg class="line-container"> <line v-for="(line, index) in lines" :key="index" :x1="line.x1" :y1="line.y1" :x2="line.x2" :y2="line.y2" /> </svg> </div> </template> <script> export default { data() { return { boxes: [ { top: 50, left: 50 }, { top: 50, left: 200 }, { top: 200, left: 50 }, { top: 200, left: 200 } ], lines: [] } }, methods: { startDrag(event, item) { const startX = event.pageX const startY = event.pageY const startTop = item.top const startLeft = item.left const moveHandler = (event) => { const deltaX = event.pageX - startX const deltaY = event.pageY - startY item.top = startTop + deltaY item.left = startLeft + deltaX } const upHandler = () => { document.removeEventListener('mousemove', moveHandler) document.removeEventListener('mouseup', upHandler) this.updateLines() } document.addEventListener('mousemove', moveHandler) document.addEventListener('mouseup', upHandler) }, updateLines() { const boxes = this.$el.querySelectorAll('.box') const lines = [] for (let i = 0; i < boxes.length; i++) { const box1 = boxes[i] const box1Rect = box1.getBoundingClientRect() for (let j = i + 1; j < boxes.length; j++) { const box2 = boxes[j] const box2Rect = box2.getBoundingClientRect() const line = { x1: box1Rect.left + box1Rect.width / 2, y1: box1Rect.top + box1Rect.height / 2, x2: box2Rect.left + box2Rect.width / 2, y2: box2Rect.top + box2Rect.height / 2 } lines.push(line) } } this.lines = lines } } } </script> <style> .container { position: relative; width: 400px; height: 400px; background-color: #f1f1f1; } .box { position: absolute; width: 50px; height: 50px; background-color: #fff; border: 1px solid #ddd; display: flex; justify-content: center; align-items: center; cursor: move; } .box span { font-size: 20px; } .line-container { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } </style> ``` 这里的核心思路是,当鼠标按下时记录当前元素的位置,然后在鼠标移动时计算偏移量,从而更新元素的位置。每次更新位置时,都重新计算连线的位置。具体实现方法是,使用 `getBoundingClientRect()` 方法获取元素的位置和尺寸,然后计算两个元素的中心点坐标,从而确定连线的起点和终点坐标。最后用 SVG 的 `line` 元素来绘制连线

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值