zha_zi 发表于 2013-1-29 08:43:32

基于html5 的拖拽连线

http://dl.iteye.com/upload/attachment/0075/5037/8e381798-1fc6-3f0a-adc7-087e6f9aee3b.jpg
 

http://dl.iteye.com/upload/attachment/0075/5039/dada324d-cd01-31a1-ab96-b77d7e97043c.jpg
        因为要实现拖拽连线研究了一下基于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;       functionPos(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=newNewImage(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=newNewImage(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=newNewImage(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.img.setDraggable(false);            }       }else{       flag=false;               for(var i=0;i<imgArray.length;i++){               imgArray.img.setDraggable(true);       imgArray.img.on('mouseover',function(){       var p=new Pos(this.getX(),this.getY());       tmpMoveImg=getImgByPos(p);            })            imgArray.img.on('dragmove',function(){               for(var j=0;j<tmpMoveImg.opsArray.length;j++){            var realPoints=[];         calculateStartEndPos(tmpMoveImg.opsArray.img,this,realPoints);      var line= createLine(realPoints);      var oldLine=tmpMoveImg.opsArray.line;      var p=new Pos(tmpMoveImg.opsArray.img.getX(),tmpMoveImg.opsArray.img.getY());      var oppoImg= getImgByPos(p);       replaceOppoLine(oppoImg,oldLine,line);      layer.remove(tmpMoveImg.opsArray.line);       tmpMoveImg.opsArray.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.img.on('mousedown',function(){                if(flag){      var pos= stage.getMousePosition();          points.push(this.getX());      points.push(this.getY());      innerFlag=true;      }       });       imgArray.img.on('mouseup',function(){      if(flag&&innerFlag){      var pos= stage.getMousePosition();          points.push(this.getX());      points.push(this.getY());                           var p=new Pos(points,points);             var op=new Pos(points,points); 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.img.getX()==pos.x&&imgArray.img.getY()==pos.y){      return imgArray;      }       }      }       /**       * 替换对方中line       */       function replaceOppoLine(imgObj,oldLine,newLine){       for(var i=0;i<imgObj.opsArray.length;i++){               if(imgObj.opsArray.line==oldLine){      imgObj.opsArray.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);       realPoints.push(arrayy);       realPoints.push(arrayx);       realPoints.push(arrayy);            }       /**       计算开始和结束节点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);       }       returnarrayX;       }       /**       计算开始和结束节点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));            }      returnarrayY;       }       /**       画图       */       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>http://dl.iteye.com/upload/attachment/0070/8176/f9bb5503-b35b-3a45-abb1-0241a1495665.png http://dl.iteye.com/upload/attachment/0070/8178/54c788d0-1395-3824-aea1-280b70b6f523.png  效果如下
http://dl.iteye.com/upload/attachment/0070/6648/40e36fc5-57b4-33da-a5f1-d73a3996261c.png
 
http://dl.iteye.com/upload/attachment/0070/6646/3b1a389b-7f5b-3ded-8dd6-d2838b933da3.png
 代码里还有一项基于extjs4 的实现和纯html5 canvas 的实现
页: [1]
查看完整版本: 基于html5 的拖拽连线