`
zha_zi
  • 浏览: 585370 次
  • 性别: 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。。

相关推荐

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

    基于jquery,利用canvas自带的api,实现了一个鼠标点击对应点后,可拖动的一个插件

    基于JavaScrips脚本设计软件的HTML实现

    轻松的拖拽单元和连线就可以编程 基于JavaScript,可应用于Web平台,开发简单 支持 Electron 可应用于桌面平台 支持调试,单步执行,变量查看 可自定义代码块,快速将您的代码嵌入 未来可能会开发基于C语言的解释器...

    Javascript图元绘制库ternlight.zip

    基于HTML CANVAS API的Javascript库,提供在HTML页面上绘制图元——如流程图的能力。 目前已支持简单的矩形图元和图元间的连线(直线、直角连线两种),拖拽图元等能力。 该javascript library的实现借鉴了...

    5个亲测好用的基于javascript的开源网页流程图、结构图

    可在客户端编辑节点 ,获取节点所有信息并显示,放大缩小视图,看见节点相关明细, 设置连线方式 ,能在现有节点上增加新的节点,能在框上移动节点位置,伸缩节点大小,在界面中拖动,拖入基本元素并布局,能分别...

    blog-demo:博客演示

    一、前端webrtc基础 —— 录音篇利用webrtc进行声音录制,转成pcm文件、wav文件,canvas画音域图,文件播放掘金地址:二、自定义H5 video 播放器基于HTML5标签实现的一个自定义视频播放器。其中实现了播放暂停、进度...

    web基于jquery拓扑图生成插件 jquery.jsPlumb-1.4.0-all.rar

    jsPlumb是一个强大的JavaScript连线库,它可以将html中的元素用箭头、曲线、直线等连接起来,适用于开发Web上的图表、建模工具等。它同时支持jQuery+jQuery UI、MooTools和YUI3这三个JavaScript框架,十分强大。大家...

    node-blueprint:基于JavaScript的可视化脚本编辑器

    轻松的拖拽单元和连线就可以编程 基于JavaScript,可规范的Web平台,开发简单 支持Electron可替代桌面平台 支持调试,单步执行,变量查看 可自定义代码块,快速将您的代码嵌入 未来可能会开发基于C语言的解释器,...

    snap_setup_1_4.exe

    Snap!是知名的e-learning软件提供商Trivantis集团最新推出的一款e-learnin课件制作...如选择对错,单项选择,多项选择,填空题,连线题,拖动题,热点区域等。 ·可在ppt当中插入web元素如一个网页,一个网上flash视

    详解如何在react中搭建d3力导向图

    实现效果:连线有箭头,点击节点能改变该节点颜色和所连接的线的粗细,缩放、拖拽。 版本:4.X 安装和导入 npm安装:npm install d3 前端导入:import * as d3 from ‘d3’; 一、完整代码 import React, { ...

Global site tag (gtag.js) - Google Analytics