Skip to content

Instantly share code, notes, and snippets.

@pridkett
Forked from knowuh/gist:205638
Created December 6, 2009 03:24
Show Gist options
  • Save pridkett/250026 to your computer and use it in GitHub Desktop.
Save pridkett/250026 to your computer and use it in GitHub Desktop.
/**
* Arrow 'plugin' for Raphael
**/
Raphael.fn.arrow = function(startx,starty,endx,endy,len,angle,color) {
var arrow;
if (startx.path && startx.type && startx.type == "arrow") {
arrow = startx;
path = arrow.path;
startx = arrow.startx; starty = arrow.starty;
endx = arrow.endx; endy = arrow.endy;
len = arrow.len; angle = arrow.angle; color = arrow.color;
}
color = typeof(color) != 'undefined' ? color : "#888";
var theta = Math.atan2((endy-starty),(endx-startx));
var baseAngleA = theta + angle * Math.PI/180;
var baseAngleB = theta - angle * Math.PI/180;
var tipX = endx + len * Math.cos(theta);
var tipY = endy + len * Math.sin(theta);
var baseAX = endx - len * Math.cos(baseAngleA);
var baseAY = endy - len * Math.sin(baseAngleA);
var baseBX = endx - len * Math.cos(baseAngleB);
var baseBY = endy - len * Math.sin(baseAngleB);
var pathData = " M " + tipX + " " + tipY +
" L " + baseAX + " " + baseAY +
" L " + baseBX + " " + baseBY +
" Z ";
if (arrow && arrow.path) {
arrow.path.attr({path: pathData});
} else
return {
path: this.path(pathData).attr({fill: color, stroke: "none"}),
type: 'arrow',
startx: startx, starty: starty,
endx: endx, endy: endy,
len: len, angle: angle, color: color
};
};
Raphael.fn.connection = function (obj1, obj2, line, bg) {
if (obj1.line && obj1.from && obj1.to) {
line = obj1;
arrow = obj1.arrow;
obj1 = line.from;
obj2 = line.to;
}
var bb1 = obj1.getBBox();
var bb2 = obj2.getBBox();
var p = [{x: bb1.x + bb1.width / 2, y: bb1.y - 1},
{x: bb1.x + bb1.width / 2, y: bb1.y + bb1.height + 1},
{x: bb1.x - 1, y: bb1.y + bb1.height / 2},
{x: bb1.x + bb1.width + 1, y: bb1.y + bb1.height / 2},
{x: bb2.x + bb2.width / 2, y: bb2.y - 1},
{x: bb2.x + bb2.width / 2, y: bb2.y + bb2.height + 1},
{x: bb2.x - 1, y: bb2.y + bb2.height / 2},
{x: bb2.x + bb2.width + 1, y: bb2.y + bb2.height / 2}];
var d = {}, dis = [];
for (var i = 0; i < 4; i++) {
for (var j = 4; j < 8; j++) {
var dx = Math.abs(p[i].x - p[j].x),
dy = Math.abs(p[i].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))) {
dis.push(dx + dy);
d[dis[dis.length - 1]] = [i, j];
}
}
}
if (dis.length == 0) {
var res = [0, 4];
} else {
var res = d[Math.min.apply(Math, dis)];
}
var x1 = p[res[0]].x,
y1 = p[res[0]].y,
x4 = p[res[1]].x,
y4 = p[res[1]].y,
dx = Math.max(Math.abs(x1 - x4) / 2, 10),
dy = Math.max(Math.abs(y1 - y4) / 2, 10),
x2 = [x1, x1, x1 - dx, x1 + dx][res[0]].toFixed(3),
y2 = [y1 - dy, y1 + dy, y1, y1][res[0]].toFixed(3),
x3 = [0, 0, 0, 0, x4, x4, x4 - dx, x4 + dx][res[1]].toFixed(3),
y3 = [0, 0, 0, 0, y1 + dy, y1 - dy, y4, y4][res[1]].toFixed(3);
var path = ["M", x1.toFixed(3), y1.toFixed(3), "C", x2, y2, x3, y3, x4.toFixed(3), y4.toFixed(3)].join(",");
/* if there was a line passed in, we can just update the path */
if (line && line.line) {
line.bg && line.bg.attr({path: path});
line.line.attr({path: path});
arrow.startx = x3; arrow.starty = y3;
arrow.endx = x4; arrow.endy = y4;
this.arrow(arrow);
} else {
var color = typeof line == "string" ? line.split("|")[0] : "#000";
var strokeWidth = line.split("|")[1] || 5;
return {
bg: bg && bg.split && this.path(path).attr({stroke: bg.split("|")[0], fill: "none", "stroke-width": strokeWidth}),
line: this.path(path).attr({stroke: color, fill: "none", "stroke-width": strokeWidth}),
// arrow: this.arrow(x3,y3,x4,y4,strokeWidth * 2.0,50,color),
arrow: this.arrow(x3,y3,x4,y4, strokeWidth * 2.0,50,color),
from: obj1,
to: obj2
};
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment