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