基于html5 拖拽连线加强版实现

    自动折线,自动判断起始点坐标,拖拽位置变换,大小拖拽,箭头指向等功能,这个版本稍微复杂一点,

还有个简单版本的实现http://zha-zi.iteye.com/blog/1586814 这个应该比较容易理解坐标换算不太多

<!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 arrowAngle=30;
       /**
       		箭头半径
       */
       
       var arrowRadius=5;
       /**
        	箭头长度
       */
       var arrowLenght=10;
       /**
       		表示方向
       */
       var E="E";
       var W="W";
       var S="S";
       var N="N";
       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;
       }; 
       /**
       		img 图像
       		lineArrow 带有箭头的line
       		flag 图像与箭头的指向关系
       */
       function LineImage(img,lineArrow,flag){
       		this.img=img;
       		this.lineArrow=lineArrow;
       		this.flag=flag
       };
       
       function LineArrow(line,arrow){
       		this.line=line;
       		this.arrow=arrow;
       };
       function NewImage(img,opsArray,group){
       		this.img=img;
       		this.group=group;
       		this.opsArray=opsArray; 
       };
        
       var imgA= new Image();
       var imgObjA;
       var groupA;
       imgA.onload=function(){
	       imgObjA= createImage(imgA,100,100,100,100)
           var array=new Array(); 
          
           groupA=new Kinetic.Group({ 
       			draggable:true
           }); 
	       groupA.add(imgObjA); 
	       layer.add(groupA);
	       addAnchor(groupA, 100, 100, "topLeft");
	       addAnchor(groupA, 200, 100, "topRight");
	       addAnchor(groupA, 200, 200, "bottomRight");
	       addAnchor(groupA, 100, 200, "bottomLeft");
	       var na=new  NewImage(imgObjA,array,groupA); 
           imgArray.push(na); 
       	   stage.add(layer); 
       } 
       
       var imgB= new Image();
       var imgObjB;
       var groupB;
       imgB.onload=function(){
       	   imgObjB= createImage(imgB,400,400,100,100)
       	   var array=new Array(); 
          
       	   groupB=new Kinetic.Group({ 
       			draggable:true
           }); 
	       groupB.add(imgObjB); 
	       layer.add(groupB);
	       addAnchor(groupB, 400, 400, "topLeft");
	       addAnchor(groupB, 500, 400, "topRight");
	       addAnchor(groupB, 500, 500, "bottomRight");
	       addAnchor(groupB, 400, 500, "bottomLeft");
	       var nb=new  NewImage(imgObjB,array,groupB);
           imgArray.push(nb);
           
       	   stage.add(layer); 
       } 
       
       var imgC= new Image();
       var imgObjC;
       var groupC;
       imgC.onload=function(){ 
       	   imgObjC= createImage(imgC,700,100,100,100) 
           var array=new Array(); 
         
       	   groupC=new Kinetic.Group({ 
       			draggable:true
           }); 
	       groupC.add(imgObjC); 
	       layer.add(groupC);
	       addAnchor(groupC, 700, 100, "topLeft");
	       addAnchor(groupC, 800, 100, "topRight");
	       addAnchor(groupC, 800, 200, "bottomRight");
	       addAnchor(groupC, 700, 200, "bottomLeft");
	       var nc=new  NewImage(imgObjC,array,groupC); 
           imgArray.push(nc);
	       
       	   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].group.setDraggable(false);
       				
       			}
       		}else{
       			flag=false;
       		 
       			for(var i=0;i<imgArray.length;i++){
       			   
       				imgArray[i].group.setDraggable(true);
       				imgArray[i].img.on('mouseover',function(){
       					
       					var p=new Pos(this.getAbsolutePosition().x,this.getAbsolutePosition().y);
       					tmpMoveImg=getImgByPos(p); 
       					
       				});
       				
       				imgArray[i].group.on('dragmove',function(){ 
       						
       				   		for(var j=0;j<tmpMoveImg.opsArray.length;j++){
				        	    var realPoints=[];  
				        	    
				        	    if(tmpMoveImg.opsArray[j].flag){
				        	    	calculateStartEndPos(tmpMoveImg.opsArray[j].img,this.children[0],realPoints);
				        	    }else{
				        	    	calculateStartEndPos(this.children[0],tmpMoveImg.opsArray[j].img,realPoints);
				        	    } 
					        	tmpMoveImg.opsArray[j].lineArrow.line.setPoints(realPoints); 
					        	var arrowPoint= calculateArrowPointsByPoints(realPoints);
					        	tmpMoveImg.opsArray[j].lineArrow.arrow.setPoints(arrowPoint);  
				       			layer.draw(); 
				       			realPoints=[]; 
				        	}
				        	layer.draw(); 
				    });
				    imgArray[i].group.on('dragmove',function(){
				    	 for(var j=0;j<lineArray.length;j++){
				    	 	//lineArray[j].hide();
				    	 	//moveLineToTarget(lineArray[j])
				    	 }
				    });
				   
				   
       			}
       		}
       		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=[];
	       			 	points.push(this.getAbsolutePosition().x);
	       			 	points.push(this.getAbsolutePosition().y);
	       			 	innerFlag=true;
	       			 }
	       		});
	       		imgArray[i].img.on('mouseup',function(){
	       			 if(flag&&innerFlag){
	       			 	var pos= stage.getMousePosition();  
	       			 	points.push(this.getAbsolutePosition().x);
	       			 	points.push(this.getAbsolutePosition().y);
	       			  	//起始点
	       		 	    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 lineArrow= createLine(realPoints); 
							var opLine=new LineImage(opImg.img,lineArrow,true);
							var owLine=new LineImage(owImg.img,lineArrow,false);  
							owImg.opsArray.push(opLine); 
							opImg.opsArray.push(owLine); 
		       		 	    flag=false;
		       		 	    innerFlag=false;
		       		 	    points=[];
		       		 	    realPoints=[]; 
		       		 	    lineArray.push(lineArrow);
		       		 	    layer.add(lineArrow.line); 
		       		 	    
		       		 	    layer.add(lineArrow.arrow);
		       		 	    layer.draw(); 
		       		 	    bandEventToLine(lineArrow.line);
		       		 	    
						} 
						
	       		 	    
       			     }
       		   });
            }
       })
       /**
       * 通过坐标获取Img对象
       */
       function getImgByPos(pos){ 
       		for(var i=0;i<imgArray.length;i++){ 
       			if(imgArray[i].img.getAbsolutePosition().x==pos.x&&imgArray[i].img.getAbsolutePosition().y==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 calculateStartEndPos(imgStart,imgEnd,realPoints){ 
       		var realSx=0;
       		var realSy=0;
       		var realEx=0;
       		var realEy=0;
       
       		var sx=imgStart.getAbsolutePosition().x;
       		var sy=imgStart.getAbsolutePosition().y;
       		var swidth=imgStart.getWidth();
       		var sheight=imgStart.getHeight(); 
       		var ex=imgEnd.getAbsolutePosition().x;
       		var ey=imgEnd.getAbsolutePosition().y; 
       		var ewidth=imgEnd.getWidth();
       		var eheight=imgEnd.getHeight();  
       		var array=calculateXY(sy,sheight,ey,eheight ,sx,swidth,ex,ewidth);
       		var crossArray=null;
       		if((array[0]!=array[2])&&(array[1]!=array[3])){
       			var crossArray= calculateCrossPoints(array,sy,sheight,ey,eheight ,sx,swidth,ex,ewidth);
       		} 
       		realPoints.push(array[0]);
       		realPoints.push(array[1]);
       		if(crossArray!=null) 
	       		for(var i=0;i<crossArray.length;i++){
	       			realPoints.push(crossArray[i]);
	       		}
       		realPoints.push(array[2]);
       		realPoints.push(array[3]); 
       		
       }
       	/**
       		计算连线开始和结束坐标的位置
       	*/
       function calculateXY(sy,sheight,ey,eheight,sx,swidth,ex,ewidth ){
       		 
       		 
       		var array=[];
       		if(sy==ey){ 
       			if(sx>ex){ 
       				array.push(sx);
       				array.push(sy+(sheight/2));
       				array.push(ex+ewidth);
       				array.push(sy+(eheight/2));
       			}else{
       				array.push(sx+swidth);
       				array.push(sy+(sheight/2));
       				array.push(ex);
       				array.push(sy+(eheight/2));
       			}
       			
       			
       		}else{ 
       			if(sy>ey&&(sy-ey>sheight)){
       				if(sx>ex){
       				 	if(sx-ex<swidth/2){
       				 		array.push(sx);
	       					array.push(sy+(sheight/2));
	       					array.push(ex);
	       					array.push(ey+eheight/2);
       				 	}else{
       				 		array.push(sx);
	       					array.push(sy+(sheight/2));
	       					array.push(ex+(ewidth/2));
	       					array.push(ey+eheight);
       				 	}
       					
       				 
       				}else if(sx==ex){
       					 
       					array.push(sx+(swidth/2));
       					array.push(sy);
       					array.push(ex+(ewidth/2));
       					array.push(ey+eheight);
       				}else{
       					if(ex-sx<ewidth/2){
       						array.push(sx);
	       					array.push(sy+(sheight/2));
	       					array.push(ex);
	       					array.push(ey+eheight/2);
       					}else{
       						array.push(sx+swidth);
	       					array.push(sy+(sheight/2));
	       					array.push(ex+(ewidth/2));
	       					array.push(ey+eheight);
       					}
       				
       				}
       			}else if(sy<ey&&(ey-sy>eheight)){
       				if(sx>ex){
       				 	if(sx-ex<swidth/2){
       				 		array.push(sx);
       				 		array.push(sy+sheight/2);
       				 		array.push(ex);
       				 		array.push(ey+eheight/2);
       				 	}else{
       				 		array.push(sx+(swidth/2));
	       					array.push(sy+sheight);
	       					array.push(ex+ewidth);
	       					array.push(ey+(eheight/2));
       				 	}
       					
       				}else if(sx==ex){
       					 
       					array.push(sx+(swidth/2));
       					array.push(sy+sheight);
       					array.push(ex+(ewidth/2));
       					array.push(ey);
       				}else{
       					if(ex-sx<ewidth/2){
       						array.push(sx);
       						array.push(sy+sheight/2);
       						array.push(ex);
       						array.push(ey+eheight/2);
       					}else{
	       					array.push(sx+(swidth/2));
	       					array.push(sy+sheight);
	       					array.push(ex);
	       					array.push(ey+(eheight/2));
       					}
       					
       				}
       			}else{
       				if((sy<ey&&(ey-sy<eheight))||sy>ey&&(sy-ey<sheight)){
       					array.push(sx+swidth/2);
       					array.push(sy);
       					array.push(ex+ewidth/2);
       					array.push(ey);
       				} 
       			}
       			
       			
       		} 
       		return  array;
       }
       /**
       		计算折叠点的位置
       */
       function calculateCrossPoints(array,sy,sheight,ey,eheight ,sx,swidth,ex,ewidth){
       	 
       		var pointsArray=[];
       		var x=array[0];
       		var y=array[1];
       		var x1=array[2];
       		var y1=array[3];
       		var f=false;
       		if((x-x1)>0&&(y-y1)>0){
       			f=true;
       		}
       		if((x1-x)>0&&(y1-y)>0){
       			f=true;
       		}
       		/**
       			y轴的多个折叠点
       		*/
       		if((sy>ey&&sy-ey<=sheight)||(sy<ey&&ey-sy<=eheight)){
       			if(sy>ey&&sy-ey<=sheight){
       				pointsArray.push(x);
       				pointsArray.push(y1-sheight);
       				pointsArray.push(x1);
       				pointsArray.push(y1-sheight);
       				
       			}else if(sy<ey&&ey-sy<=eheight){
       				pointsArray.push(x);
       				pointsArray.push(y-eheight);
       				pointsArray.push(x1);
       				pointsArray.push(y-eheight);
       			}
       			
       		 
       		}else if((sx>ex&&sx-ex<=sheight/2)||(sx<ex&&ex-sx<=eheight/2)){
       			/**
       		 		x轴的多个折点
       		 	*/
       			//x= sx-swidth/2
       			//y=y+sheight/2
       			 
       			if(sx-ex<sheight/2){
       			 
       				pointsArray.push(sx-ewidth);
       				pointsArray.push(sy+sheight/2);
       				pointsArray.push(sx-ewidth);
       				pointsArray.push(ey+eheight/2);
       			}else if(ex-sx<eheight/2){
       			 
       				pointsArray.push(ex-swidth);
       				pointsArray.push(sy+sheight/2);
       				pointsArray.push(ex-swidth);
       				pointsArray.push(ey+eheight/2);
       			}
       			 
       		
       		}else{
       			/**
       			单个折叠点
       			*/
       			if(f){
	       			if(x<x1){
	       				pointsArray.push(x);
	       			}else{
	       				pointsArray.push(x1);
	       			}
	       			if(y<y1){
	       				pointsArray.push(y1);
	       			}else{
	       				pointsArray.push(y);
	       			}
	       		}else{ 
	       			if(x<x1){
	       				pointsArray.push(x1);
	       			}else{
	       				pointsArray.push(x);
	       			}
	       			if(y<y1){
	       				pointsArray.push(y1);
	       			}else{
	       				pointsArray.push(y);
	       			}
	       		}
       		}
       		 
       		
       		return pointsArray;
       }
       function createImage(img,x,y,width,height){
       		var imgObj=new Kinetic.Image({
	       		x:x,
	       		y:y,
	       		width:width,
	       		height:height, 
	       		//draggable:true,
	       		image:img,
	       		name:"image",
	       });
	       imgObj.on("mouseover", function(){
                document.body.style.cursor = "pointer";
           });
           imgObj.on("mouseout", function(){
                document.body.style.cursor = "default";
           });
           return imgObj
       	
       } 
       
        /**
       		根据points 节点数组划线
       */
       function createLine(points){ 
       		 
			var line=new Kinetic.Line({ 
		  		points:points,
		  		stroke:'green', 
		  		strokeWidth:2, 
		  		lineCap:'round',
		  		lineJoin:'round' 
		 	 	
	 	    });
	 	    var lenght=points.length; 
	 	    var x=points[lenght-4];
	 	    var y=points[lenght-3];
	 	    var x1=points[lenght-2];
	 	    var y1=points[lenght-1];  
	 	    var arrow=createArrow(calculateArrowPosition(x1,y1,calculateArrowAspect(x,y,x1,y1)),"black");
	 	    
	 	    var la =new LineArrow(line,arrow);
	 	    return la;
       }
       function bandEventToLine(line){
     	   line.saveData();
		       		 	   
       	   line.on("mouseover", function(){
                document.body.style.cursor = "pointer";
           });
           line.on("mouseout", function(){
                document.body.style.cursor = "default";
           });
       }
       /**
       		通过line计算 arrow 的points 数组
       */
       function calculateArrowPointsByLine(line){
       		var points=line.getPoints();
       		var lenght=points.length; 
	 	    var x=points[lenght-4];
	 	    var y=points[lenght-3];
	 	    var x1=points[lenght-2];
	 	    var y1=points[lenght-1];  
	 	    return calculateArrowPosition(x1,y1,calculateArrowAspect(x,y,x1,y1));
	 	     
       }
       function calculateArrowPointsByPoints(points){
       		var lenght=points.length;
       		var x=points[lenght-4];
	 	    var y=points[lenght-3];
	 	    var x1=points[lenght-2];
	 	    var y1=points[lenght-1]; 
	 	    return calculateArrowPosition(x1,y1,calculateArrowAspect(x,y,x1,y1));
       }
       /**
       	 计算箭头朝向
       */
       function calculateArrowAspect(x,y,x1,y1){
       		 
       		if(x==x1){
       			if(y>y1){
       				return N;
       			}else{
       				return S;
       			}
       		}else if(y==y1){
       			if(x>x1){
       				return W;
       			}else{
       				return E;
       				
       			}
       		}
       }
       
       /**
       	  计算箭头具体位置
       */
       function calculateArrowPosition(x,y,aspect){
       		 
       		var points=[];
       		switch(aspect){
       			case N:
       				points.push(x);
       				points.push(y);
       				points.push(x-arrowRadius);
       				points.push(y+arrowLenght);
       				points.push(x+arrowRadius);
       				points.push(y+arrowLenght); 
       				break;
       			case S:
       				points.push(x);
       				points.push(y);
       				points.push(x-arrowRadius);
       				points.push(y-arrowLenght);
       				points.push(x+arrowRadius);
       				points.push(y-arrowLenght);
       			 
       				break;
       			case E:
       				points.push(x);
       				points.push(y);
       				
       				points.push(x-arrowLenght);
       				points.push(y+arrowRadius);  
       				
       				points.push(x-arrowLenght);
       				points.push(y-arrowRadius);
       				
       				break;
       			case W:
       				points.push(x);
       				points.push(y);
       				points.push(x+arrowLenght);
       				points.push(y+arrowRadius);  
       				
       				points.push(x+arrowLenght);
       				points.push(y-arrowRadius);
       				
       				break;
       		}
       	 
       		return points;
       }
       function createArrow(points,fill){
       		var arrow=new Kinetic.Polygon({
       			  points: points,
		          fill: fill,
		          stroke: "black",
		          strokeWidth: 1
       		}); 
       		return arrow;
       }
       function addAnchor(group,x,y,name){
       		var stage=group.getStage();
       		var layer=group.getLayer();
       		var anchor=new Kinetic.Circle({
       			x:x,
       			y:y,
       			stroke:'#666',
       			fill:'green',
       			radius:1,
       			name:name,
       			draggable:true
       		});
       		anchor.on('dragmove',function(){
       			 update(group, this);
       			 layer.draw();
       		});
       		anchor.on('dragend',function(){
       			group.setDraggable(true);
         		 layer.draw();
       		
       		});
       		anchor.on('mousedown touchstar',function(){
       			group.setDraggable(false);
          		//this.moveToTop();
       		
       		});
       		anchor.on('mouseover',function(){
      			  var layer = this.getLayer();
		          document.body.style.cursor = "pointer";
		          this.setRadius(3);
		          layer.draw();
       		
       		});
       		anchor.on('mouseout',function(){
       			  var layer = this.getLayer();
		          document.body.style.cursor = "default";
		          this.setRadius(1);
		          layer.draw();
       			
       		});
       		group.add(anchor);
       }
       function update(group,activeAnchor){
       		var topLeft=group.get(".topLeft")[0];
       		var topRight=group.get(".topRight")[0];
       		var bottomLeft=group.get(".bottomLeft")[0];
       		var bottomRight=group.get(".bottomRight")[0];
       		
       		var image=group.children[0]; 
       		
       		switch(activeAnchor.getName()){
       			 case "topLeft":
		            topRight.attrs.y = activeAnchor.attrs.y;
		            bottomLeft.attrs.x = activeAnchor.attrs.x;
		            break;
		          case "topRight":
		            topLeft.attrs.y = activeAnchor.attrs.y;
		            bottomRight.attrs.x = activeAnchor.attrs.x;
		            break;
		          case "bottomRight":
		            bottomLeft.attrs.y = activeAnchor.attrs.y;
		            topRight.attrs.x = activeAnchor.attrs.x;
		            break;
		          case "bottomLeft":
		            bottomRight.attrs.y = activeAnchor.attrs.y;
		            topLeft.attrs.x = activeAnchor.attrs.x;
		            break;
       		}
       	 
       		image.setPosition(topLeft.attrs.x, topLeft.attrs.y);
       		image.setSize(topRight.attrs.x - topLeft.attrs.x, bottomLeft.attrs.y - topLeft.attrs.y);
       }
       
       
        
    }); 

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

基于html5 拖拽连线加强版实现_第1张图片

 
基于html5 拖拽连线加强版实现_第2张图片

 

 

 

你可能感兴趣的:(canvas,html5)