Brief history of this code:
Hi, friends i am learning Raphael js and creating an application in it. i needed to create a mechanism which would allow more than one connections between two Raphael rectangles and i was having alot of i mean tons of issues and thoughts on how to do it and it kept me busy a lot. i was so tired that i had to make stackoverflow account and ask help about it, but the help i got added one more thought to me. At last i am able to create a mechanism which will not only allow more than one connection but also renders it on moving the rectangle. yes i know it still has issues but this is the basic code to help any other who need this and can use it and don't have struggle as much as i did.Lets get started:
create and HTML document and use the following code: <!doctype html>  
 <html>  
 <body>  
      <div id="canvas"></div>  
      <script type="text/javascript" src="js/Raphael.js"></script>  
      <script type="text/javascript" src="js/app.js"></script>  
 </body>  
 </html>  
in the app.js use the following code:
 function lineDistance( point1, point2 )  
 {  
  var xs = 0;  
  var ys = 0;  
  xs = point2.x - point1.x;  
  xs = xs * xs;  
  ys = point2.y - point1.y;  
  ys = ys * ys;  
  return Math.sqrt( xs + ys );  
 }  
 Raphael.fn.connection = function (objFrom, objTo, line, bg) {  
   if (objFrom.line && objFrom.from && objFrom.to) {  
     line = objFrom;  
     objFrom = line.from;  
     objTo = line.to;  
   }  
   var bb1 = objFrom.getBBox(),  
     bb2 = objTo.getBBox();  
     var obj1freeNodes = objFrom.data('freeNodes');  
     var obj2freeNodes = objTo.data('freeNodes');  
     var p = [];  
     obj1freeNodes.forEach(function (el) {  
     p.push(el);  
    })  
     obj2freeNodes.forEach(function (el) {  
     p.push(el);  
    })  
     var distance = [], d = {};  
     for (var i = 0; i <obj1freeNodes.length; i++) {  
     for (var j = obj1freeNodes.length; j <p.length; j++) {  
        var point1 = {x:p[i].x, y: p[i].y};  
        var point2 = {x:p[j].x, y: p[j].y};  
       if ((i == j - 4) || (((i != 3 && j != 6) || p[i].x < p[j].x) && ((i != 2 && j != 7) || p[i].x > p[j].x) && ((i != 0 && j != 5) || p[i].y > p[j].y) && ((i != 1 && j != 4) || p[i].y < p[j].y))) {  
         distance.push(lineDistance(point1, point2));  
        d[distance[distance.length - 1]] = [i, j];  
       }  
     }  
   }  
     if (distance.length == 0) {  
      var res = [0, obj1freeNodes.length];  
    } else {  
      res = d[Math.min.apply(Math, distance)];  
    }  
    var x1 = p[res[0]].x,  
      y1 = p[res[0]].y,  
      x4 = p[res[1]].x,  
      y4 = p[res[1]].y;  
    //remove to connecting point  
    for(var i=0;i<obj1freeNodes.length; i++){  
    if(i== res[0]){  
      obj1freeNodes.splice(i,1);   
     }  
    }  
    for(var i=0;i<obj2freeNodes.length; i++){  
    if(i == (res[1]-obj1freeNodes.length-1)){  
      obj2freeNodes.splice(i,1);   
     }  
    }  
   objFrom.data('freeNodes', obj1freeNodes);  
   objTo.data('freeNodes', obj2freeNodes);  
   p = [];  
     var path = ["M", x1.toFixed(3), y1.toFixed(3), "L", /*x2, y2, x3, y3,*/ x4.toFixed(3), y4.toFixed(3)].join(",");  
   if (line && line.line) {  
     line.bg && line.bg.attr({path: path});  
     line.line.attr({path: path});  
   } else {  
     var color = typeof line == "string" ? line : "#000";  
           var conLine = this.path(path).attr({  
          stroke: color,  
          fill: "none",  
          "arrow-end": "block-wide-long",  
          "stroke-width": 3,  
          });  
           pathObj = {  
        bg: bg && bg.split && this.path(path).attr({  
          stroke: bg.split("|")[0],  
          fill: "none",  
          "stroke-width": bg.split("|")[1] || 3  
        }),  
        line: conLine,  
        from: objFrom,  
        to: objTo,  
      };  
      return pathObj;  
   }  
 };  
 Raphael.el.getNodes = function()  
   {  
    //calculate the element nodes and return them  
    var obj = this.getBBox();  
    var objX = parseInt(obj.x);  
    var objY = parseInt(obj.y);  
    var objWidth = parseInt(obj.width);  
    var objHeight = parseInt(obj.height);  
    var maxCons = 8;  
    var scaleCut = 10;  
    var topPositions = [], rightPositions = [], bottomPositions = [], leftPositions = [];  
    //get all possible connectors based on maxCons and scaleCut  
   var objCons = [];  
   for(var i= 0; i<maxCons; i++){  
     topPositions.push({x: (objX + ((objWidth-scaleCut)/maxCons)*i)+i*2, y: objY-1});  
     rightPositions.push({x: objX + objWidth + 1, y: (objY + ((objHeight-scaleCut)/maxCons)*i)+i*2});  
     bottomPositions.push({x: ((objX+3) + ((objWidth-(scaleCut-2))/maxCons)*i)+i*2, y: objY + objHeight +1});  
     leftPositions.push({x: objX - 1, y: ((objY+4) + ((objHeight-(scaleCut+1))/maxCons)*i)+i*2});    
    }  
    // push all positions to objCons array   
   pushArryToArray(topPositions, objCons);  
   pushArryToArray(rightPositions, objCons);  
   pushArryToArray(bottomPositions, objCons);  
   pushArryToArray(leftPositions, objCons);  
   //this.data('freeNodes',objCons);  
    return objCons;  
   }  
 //pushes one array contents to another array  
 var pushArryToArray = function(sourceArr, targetArr){  
  for(var i=0; i<sourceArr.length;i++){  
    // draw connecting points  
    // R.circle(sourceArr[i].x,sourceArr[i].y,2).attr({'fill':'red', 'stroke':'none'});  
    targetArr.push(sourceArr[i]);  
   }  
 }  
 var R = Raphael("canvas","400","400");  
 //window.onload = function() {  
 start = function() {  
     this.ox = this.attr("x");  
     this.oy = this.attr("y");  
     this.animate({  
       opacity: .75  
     }, 500, ">");  
 }  
 move = function(dx, dy) {  
  this.attr({  
      x: this.ox + dx,  
      y: this.oy + dy  
     });  
   //on moving events reintializing free nodes of all events   
   for(var i = 0; i<arrAllEvents.length; i++){  
      arrAllEvents[i].data('freeNodes', arrAllEvents[i].getNodes());  
     }  
   //rendering connections on event move  
   for (var i = connections.length; i--;) {  
     R.connection(connections[i]);  
   }  
    R.safari();  
 }  
 up = function() {  
 }  
 var eventOne = R.rect(10,10,100, 100).attr({  
       fill: Raphael.getColor(),  
       stroke: "none",  
       cursor: "move"  
     });  
 var eventTwo = R.rect(220,10,100, 100).attr({  
       fill: Raphael.getColor(),  
       stroke: "none",  
       cursor: "move"  
     });  
 var eventThree = R.rect(220,220,100, 100).attr({  
       fill: Raphael.getColor(),  
       stroke: "none",  
       cursor: "move"  
     });  
 //intializing free connecting nodes 1st time  
 eventOne.data('freeNodes', eventOne.getNodes());  
 eventTwo.data('freeNodes', eventTwo.getNodes());  
 eventThree.data('freeNodes', eventThree.getNodes());  
 //storing all events in array  
 var arrAllEvents = []  
 arrAllEvents.push(eventOne);  
 arrAllEvents.push(eventTwo);  
 arrAllEvents.push(eventThree);  
 //to draw the connections b/w events  
 var connections = [];  
 connections.push(R.connection(eventOne, eventTwo, Raphael.getColor()));  
 connections.push(R.connection(eventOne, eventTwo, Raphael.getColor()));  
 connections.push(R.connection(eventOne, eventTwo, Raphael.getColor()));  
 connections.push(R.connection(eventOne, eventThree, Raphael.getColor()));  
 connections.push(R.connection(eventOne, eventThree, Raphael.getColor()));  
 //dragging events  
 for(var i = 0; i<arrAllEvents.length; i++){  
      arrAllEvents[i].drag(move, start, up);  
     }  
 //}  
View it on Jsfiddle
Please let me know about my this effort, or to make it much more useful.
 

so great .................. and thanks to share it
ReplyDeleteThanks
DeletePurchase website, app, domain
ReplyDelete