`
zha_zi
  • 浏览: 592944 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

基于html5 的拖拽连线

阅读更多


 


        因为要实现拖拽连线研究了一下基于extjs 和html5的不同实现方法

extjs底层的画图引擎是svg 不知道在html5大潮即将袭来的前夕一贯走在技术前沿的extjs开发团队没有自己封装基于html5的画图引擎,而是选择了svg 。

      下边是花了不到一天的时间实现的任意点连线和拖动功能,代码没有优化,稍微乱了点

      如果单纯应用canvas进行画图,拖拽是非常麻烦的,我们往往要基于第三方的画图类库,这里实现是基于kineticjs

      为了测试方便我使用了双击事件控制拖动还是划线  。

      代码

<!DOCTYPE HTML>
<html>
  <head>
    <style>
      body {
        margin: 0px;
        padding: 0px;
      }
      canvas {
        border: 1px solid #9C9898;
      }
    </style>
    	<script type="text/javascript" src="ext/bootstrap.js"></script> 		
		<!-- ENDLIBS -->
		<script type="text/javascript" src="ext/ext-all-debug.js"></script>
    <script src="js/kinetic-v3.10.2.min.js"></script>
    <script>
    
    Ext.onReady(function(){
    	/**
			自动判断顶点连线算法
		*/    	
       
       var stage=new Kinetic.Stage({
       		container:'container',
       		width:1000,
       		height:1000
       });
       var layer=new Kinetic.Layer();
       var flag=false;
       var imgArray=[]; 
       var lineArray=[];
       var tmpMoveImg=null;
       var loop=0;
       function  Pos(x,y){
       		this.x=x;
       		this.y=y;
       }; 
       function LineImage(img,line){
       		this.img=img;
       		this.line=line;
       };
       
       function NewImage(img,opsArray){
       		this.img=img;
       		this.opsArray=opsArray; 
       };
        
       var imgA= new Image();
       imgA.onload=function(){
	       var imgObjA= createImage(imgA,100,100,100,100)
           var array=new Array(); 
           var na=new  NewImage(imgObjA,array); 
           imgArray.push(na);
       	   layer.add(imgObjA);
       	   stage.add(layer); 
       } 
       
       var imgB= new Image();
       imgB.onload=function(){
       	   var imgObjB= createImage(imgB,400,400,100,100)
       	   var array=new Array(); 
           var nb=new  NewImage(imgObjB,array);
           imgArray.push(nb);
       	   layer.add(imgObjB);
       	   stage.add(layer); 
       } 
       
       var imgC= new Image();
       imgC.onload=function(){ 
       	   var imgObjC= createImage(imgC,700,100,100,100) 
           var array=new Array(); 
           var nc=new  NewImage(imgObjC,array); 
           imgArray.push(nc);
       	   layer.add(imgObjC);
       	   stage.add(layer); 
       }  
       var rect=new Kinetic.Rect({
       		x:0,
       		y:0,
       		width:1000,
       		height:1000,
       		fill:'white',
       		storke:'red',
       		storkeWidth:5
       		
       });
       layer.add(rect);  
       imgA.src='img/db.png'; 
       imgB.src='img/mj.png'; 
       imgC.src="img/kt1.png";
       rect.on('dblclick',function(){
       		
       		if(loop%2==0){
       			flag=true;
       			for(var i=0;i<imgArray.length;i++){
       				imgArray[i].img.setDraggable(false);
       				
       			}
       		}else{
       			flag=false;
       		 
       			for(var i=0;i<imgArray.length;i++){
       			   
       				imgArray[i].img.setDraggable(true);
       				imgArray[i].img.on('mouseover',function(){
       					var p=new Pos(this.getX(),this.getY());
       					tmpMoveImg=getImgByPos(p);
       					
       				})
       				
       				imgArray[i].img.on('dragmove',function(){
       				   
       					for(var j=0;j<tmpMoveImg.opsArray.length;j++){
				        	    var realPoints=[]; 
					        	calculateStartEndPos(tmpMoveImg.opsArray[j].img,this,realPoints); 
					       		var line= createLine(realPoints); 
				       			var oldLine=tmpMoveImg.opsArray[j].line; 
				       			var p=new Pos(tmpMoveImg.opsArray[j].img.getX(),tmpMoveImg.opsArray[j].img.getY()); 
				       			var oppoImg= getImgByPos(p);
				       			replaceOppoLine(oppoImg,oldLine,line); 
				       			layer.remove(tmpMoveImg.opsArray[j].line);
				       			tmpMoveImg.opsArray[j].line=line; 
				       			layer.add(line);
				       			layer.draw();
				       			realPoints=[];
				       	 
				        }  
				        
				        layer.draw();
				        
				    })
       			}
       		}
       		loop++;
       		
       		for(var i=0;i<imgArray.length;i++){
	       		var innerFlag=false;
	       		var points=[];//标记性的点,为了获取img 使用
	       		var realPoints=[];//真正计算后合理的划线点
	       		imgArray[i].img.on('mousedown',function(){
	       			 
	       			 if(flag){
	       			 	var pos= stage.getMousePosition();  
	       			 	points.push(this.getX());
	       			 	points.push(this.getY());
	       			 	innerFlag=true;
	       			 }
	       		});
	       		imgArray[i].img.on('mouseup',function(){
	       			 if(flag&&innerFlag){
	       			 	var pos= stage.getMousePosition();  
	       			 	points.push(this.getX());
	       			 	points.push(this.getY());
	       			 	
	       			  	
	       		 	    var p=new Pos(points[0],points[1]); 
	       		 	    var op=new Pos(points[2],points[3]); 
						var opImg=getImgByPos(p); 
						var owImg=getImgByPos(op);
						if(opImg!=owImg){
							calculateStartEndPos(opImg.img,owImg.img,realPoints);
		       			  	var line= createLine(realPoints);
						 	
							var opLine=new LineImage(opImg.img,line);
							var owLine=new LineImage(owImg.img,line);
							
							 
							owImg.opsArray.push(opLine); 
							opImg.opsArray.push(owLine);
		       		 	    
		       		 	    
		       		 	    flag=false;
		       		 	    innerFlag=false;
		       		 	    points=[];
		       		 	    realPoints=[];
		       		 	    layer.add(line);
		       		 	    layer.draw();
						} 
						
	       		 	    
       			     }
       		   });
            }
       })
       /**
       * 通过坐标获取Img对象
       */
       function getImgByPos(pos){ 
       		for(var i=0;i<imgArray.length;i++){ 
       			if(imgArray[i].img.getX()==pos.x&&imgArray[i].img.getY()==pos.y){ 
       				return imgArray[i]; 
       			}
       		} 
       }
       /**
       * 替换对方中line
       */
       function replaceOppoLine(imgObj,oldLine,newLine){
       		for(var i=0;i<imgObj.opsArray.length;i++){
       			 
       			if(imgObj.opsArray[i].line==oldLine){ 
       				imgObj.opsArray[i].line=newLine;
       			} 
       		}
       }
       /**
       	划线
       */
       function createLine(points){
       		 
			 var line=new Kinetic.Line({ 
		  		points:points,
		  		stroke:'bule',
		  		strokeWidth:5,
		  		lineCap:'round',
		  		lineJoin:'round' 
		 	 	
	 	    });	  
	 	    
	 	    return line;
       }
       /**
       * 计算划线的开始坐标
       */
       function calculateStartEndPos(imgStart,imgEnd,realPoints){
       		var realSx=0;
       		var realSy=0;
       		var realEx=0;
       		var realEy=0;
       
       		var sx=imgStart.getX();
       		var sy=imgStart.getY();
       		var swidth=imgStart.getWidth();
       		var sheight=imgStart.getHeight(); 
       		var ex=imgEnd.getX();
       		var ey=imgEnd.getY();
       		var ewidth=imgEnd.getWidth();
       		var eheight=imgEnd.getHeight(); 
       		
       		var arrayx=calculateX(sx,swidth,ex,ewidth );
       		
       		var arrayy=calculateY(sy,sheight,ey,eheight );
       		 
       		
       		realPoints.push(arrayx[0]);
       		realPoints.push(arrayy[0]);
       		realPoints.push(arrayx[1]);
       		realPoints.push(arrayy[1]);
       		
       }
       /**
       		计算开始和结束节点x坐标
       */
       function calculateX(sx,swidth,ex,ewidth ){
       		var arrayX=[];
       		if(sx>ex){  
       			arrayX.push(sx);
       			arrayX.push(ex+ewidth);
       		 
       		}else if(sx==ex){
       			arrayX.push(sx+(swidth/2));
       			arrayX.push(sx+(ewidth/2));
       		}else{ 
       			arrayX.push(sx+swidth);
       			arrayX.push(ex);
       		}
       		return  arrayX;
       }
       /**
       		计算开始和结束节点y坐标
       */
       function calculateY(sy,sheight,ey,eheight ){
       		 
       		 
       		var arrayY=[];
       		if(sy>ey){ 
       			arrayY.push(sy+(sheight/2));
       			arrayY.push(ey+(eheight/2));
       		}else if(sy==ey){
       			
       			arrayY.push(sy+(sheight/2));
       			arrayY.push(sy+(eheight/2));
       		}else{ 
       			arrayY.push(sy+(sheight/2));
       			arrayY.push(ey+(eheight/2));
       			
       		} 
       		return  arrayY;
       }
       /**
       		画图
       */
       function createImage(img,x,y,width,height){
       		var imgObj=new Kinetic.Image({
	       		x:x,
	       		y:y,
	       		width:width,
	       		height:height,
	       		draggable:true,
	       		image:img
	       });
	       imgObj.on("mouseover", function(){
                document.body.style.cursor = "pointer";
           });
           imgObj.on("mouseout", function(){
                document.body.style.cursor = "default";
           });
           return imgObj
       
       } 
        
    }); 

    </script>
  </head>
  <body>
    <div id="container"></div>
  </body>
</html>



 


 

 效果如下

 

 代码里还有一项基于extjs4 的实现和纯html5 canvas 的实现

  • 大小: 79.1 KB
  • 大小: 77.8 KB
  • 大小: 23.6 KB
  • 大小: 31.6 KB
分享到:
评论
8 楼 FakLove 2017-03-14  
连线如何删除啊
7 楼 FakLove 2017-03-14  
连线可以再删除吗?
6 楼 suied 2014-06-05  
可以用,感觉不如flash没有办法应用到项目
5 楼 edgar108 2012-10-23  
恩 下载了ExtDraw1,kineticLine4.html 按照你说的这5步可以画出来线,

你贴出来的代码 这么做不行,ExtDraw里面的kineticLine1.html 这么做可以。

这么细致的讲解,非常感谢!
4 楼 zha_zi 2012-10-23  
edgar108 写道
又试了好几次,还是不行

图片本身是可以拖动的,
首先要先在空白处双击这时候图片就无法拖动了”

恩 没问题。


“然后左键单击一张图片拖动到另一张就完成了划线”

这时左键单击一张图片, 图片是不能拖动的 ,怎么叫“拖动到另一张就完成了划线”

不明白。。


整个工程目录中有多个页面都可以访问,我这里使用的是http://localhost:8080/ExtDraw/kineticLine4.html 这个页面进行划线

步骤
1:双击空白页面空白,这时候图片都会被锁定,双击后不要在点击鼠标(切忌)
2:在任意一种图片上单击鼠标(千万不要松手) 摁着鼠标的左键拖向其他的任意一张图片
3:当鼠标移到其他图片上松开鼠标左键,这样就完成了一次划线
4:然后在页面空白处双击鼠标图片就可以解锁,可以重新拖动
5:重新划线就重复(1-4)

你重新下载一下ExtDraw1.zip
这里边的功能有所加强有自动折线,带箭头
3 楼 edgar108 2012-10-22  
又试了好几次,还是不行

图片本身是可以拖动的,
首先要先在空白处双击这时候图片就无法拖动了”

恩 没问题。


“然后左键单击一张图片拖动到另一张就完成了划线”

这时左键单击一张图片, 图片是不能拖动的 ,怎么叫“拖动到另一张就完成了划线”

不明白。。
2 楼 zha_zi 2012-10-21  
edgar108 写道

2个图片附件那个页面,
试了20分钟画不出来线。。
双击某一个图片,松手后再点击这个图片,再按住, 图片会和鼠标一起拖动,怎么画线?

我用的是chrome。。


图片本身是可以拖动的,
首先要先在空白处双击这时候图片就无法拖动了,
然后左键单击一张图片拖动到另一张就完成了划线
换线结束后图片又可以拖动了,这时候拖动图片就可以线随图片动。
这个版本写的比较早。
1 楼 edgar108 2012-10-20  

2个图片附件那个页面,
试了20分钟画不出来线。。
双击某一个图片,松手后再点击这个图片,再按住, 图片会和鼠标一起拖动,怎么画线?

我用的是chrome。。

相关推荐

    html5做连线题

    "html5做连线题"这个话题涉及到使用HTML5的Canvas API来实现一个在线的连线游戏或者教育工具,允许用户在网页上进行拖拽线段连接不同的元素。 Canvas是HTML5中的一个核心元素,它是一个二维绘图画布,通过...

    HTML5 Cavnas实现连线题特效

    在这个场景中,“HTML5 Canvas实现连线题特效”是指利用Canvas API来构建一种互动式的连线答题界面,用户可以通过鼠标拖动来连接不同的元素,形成正确的关联。 Canvas的基本使用涉及到以下几个核心概念: 1. 创建...

    H5+canvas+js实现连线题

    1. **HTML5 Canvas**:Canvas是一个基于矢量图形的画布元素,通过JavaScript的API,我们可以绘制点、线、图形甚至动画。在这个项目中,Canvas用于绘制连线题的背景、题目文本、选项以及连线路径。通过设置不同颜色和...

    jquery基于html5和canvas实现的连线问题代码.zip

    在本项目中,"jquery基于html5和canvas实现的连线问题代码.zip" 是一个包含JavaScript技术实现的互动图形示例。这个压缩包可能包含了用于在HTML5 Canvas上使用jQuery库来绘制和操作线条的源代码。以下是这个项目可能...

    jsPlumb开发入门教程(实现html5拖拽连线).pdf

    jsPlumb 开发入门教程(实现 html5 拖拽连线) jsPlumb 是一个强大的 JavaScript 连线库,可以将 html 中的元素用箭头、曲线、直线等连接起来,适用于开发 Web 上的图表、建模工具等。它同时支持 jQuery+jQuery UI...

    jsPlumbToolkit +ztree拖拽连线demo

    4. **创建连线**:监听拖拽事件,当用户拖动鼠标在两个节点之间创建连接时,调用 `jsPlumbToolkit` 的方法创建连线。 5. **更新数据模型**:当节点或连线发生变化时,同步更新内部的数据模型。 6. **保存与加载**:...

    基于jquery+canvas实现的拖动插件

    本项目以"基于jquery+canvas实现的拖动插件"为主题,利用jQuery与HTML5的Canvas API,创建了一个允许用户点击并拖动图形的功能。 Canvas是HTML5引入的一个强大特性,它提供了一个二维的绘图表面,开发者可以使用...

    一个基于 html5 canvas 的流程图demo..zip

    这个"一个基于html5 canvas的流程图demo.zip"文件很可能包含了一个使用HTML5 Canvas技术实现的流程图示例项目。下面将详细探讨HTML5 Canvas以及其在多媒体和游戏开发中的应用。 HTML5 Canvas是一个基于矢量图形的...

    HTML5 Canvas实现连线题特效特效代码

    本话题聚焦于利用HTML5 Canvas实现的连线题特效,这是一种常见的教育或者娱乐应用,用户可以通过拖动线段将对应的元素连接起来,通常用于训练记忆力或者逻辑思维。 首先,我们要理解Canvas的基本使用。在HTML中,...

    js和html5实现网络拓扑图

    Canvas是基于像素的画布,适合动态绘制,而SVG则是基于矢量图形,适合创建清晰、可缩放的图形。在网络拓扑图的场景中,SVG可能更为合适,因为它可以保持图形质量,即使在放大或缩小时也是如此。 Qunee是一个强大的...

    jquery基于html5和canvas实现的连线问题特效代码

    【jQuery 基于 HTML5 和 Canvas 实现的连线问题特效代码详解】 在现代Web开发中,jQuery 是一个广泛使用的JavaScript库,它简化了DOM操作、事件处理和动画效果。HTML5 的引入则为Web应用提供了更强大的功能,尤其是...

    基于HTML5的WEB流程图绘制

    在"基于HTML5的WEB流程图绘制"这个主题中,我们将深入探讨如何利用HTML5的技术特性来创建交互式的、用户友好的流程图。 首先,HTML5引入了Canvas元素,这是一个二维绘图板,允许开发者通过JavaScript进行动态图形...

    基于vue的甘特图,可上下拖拽

    标题"基于vue的甘特图,可上下拖拽"表明这个项目的核心在于Vue.js与甘特图的结合,并且重点在于实现了甘特图的任务条上下拖动的功能。这通常意味着用户可以通过鼠标操作直接调整任务的时间安排,使得界面交互更加...

    svg.js和jquery实现连线功能

    SVG是一种基于XML的矢量图形格式,它允许在网页上创建可缩放的图形,而不会失去图像质量。SVG.js是一个轻量级的JavaScript库,专为操作SVG图形而设计。它可以轻松地创建、修改、动画化SVG元素,非常适合用于构建动态...

    连线题Canvas

    【连线题Canvas】是一种基于HTML5 Canvas技术的插件,用于创建交互式的连线题。HTML5 Canvas是Web开发中的一个核心元素,它提供了一个二维绘图环境,允许开发者通过JavaScript来绘制图形,实现动态和丰富的视觉效果...

    jquery html5三维线性人物关系图特效代码

    在HTML5环境下,可以使用WebGL进行三维渲染,这是一种基于OpenGL标准的JavaScript API,能直接在浏览器中生成复杂的3D图形。 该特效代码可能包含以下关键部分: 1. 数据结构:用于存储人物信息和他们之间的关系,...

    基于HTML5的canvas技术实现自制画板,具有切换画笔颜色、撤回、清除.zip

    本项目“基于HTML5的canvas技术实现自制画板,具有切换画笔颜色、撤回、清除”旨在利用canvas的这一功能,创建一个互动性强、功能丰富的在线画板应用。 首先,`&lt;canvas&gt;`元素本身只是一个静态的矩形区域,我们需要...

    html5流程设计器

    HTML5流程设计器是一种基于Web的图形化工具,用于创建、编辑和展示流程图或工作流。这个工具利用HTML5的Canvas元素,一个用于在网页上进行动态图形绘制的API,来实现用户界面。Canvas提供了丰富的绘图功能,使得...

Global site tag (gtag.js) - Google Analytics