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

来源:互联网 发布:VB中改变窗体颜色属性 编辑:程序博客网 时间:2024/04/28 01:14

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

还有个简单版本的实现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>  

 

 

原创粉丝点击