2 * Originally grabbed from the official RaphaelJS Documentation
3 * http://raphaeljs.com/graffle.html
4 * Adopted (arrows) and commented by Philipp Strathausen http://blog.ameisenbar.de
5 * Licenced under the MIT licence.
12 * source shape [or connection for redrawing],
14 * style with { fg : linecolor, bg : background color, directed: boolean }
16 * connection { draw = function() }
18 Raphael
.fn
.connection = function (obj1
, obj2
, style
) {
20 /* create and return new connection */
26 /* get bounding boxes of target and source */
27 var bb1
= obj1
.getBBox();
28 var bb2
= obj2
.getBBox();
31 /* coordinates for potential connection coordinates from/to the objects */
33 {x: bb1.x + bb1.width / 2, y: bb1.y - off1}, /* NORTH 1 */
34 {x
: bb1
.x
+ bb1
.width
/ 2, y
: bb1
.y
+ bb1
.height
+ off1
}, /* SOUTH 1 */
35 {x
: bb1
.x
- off1
, y
: bb1
.y
+ bb1
.height
/ 2}, /* WEST 1 */
36 {x
: bb1
.x
+ bb1
.width
+ off1
, y
: bb1
.y
+ bb1
.height
/ 2}, /* EAST 1 */
37 {x
: bb2
.x
+ bb2
.width
/ 2, y
: bb2
.y
- off2
}, /* NORTH 2 */
38 {x
: bb2
.x
+ bb2
.width
/ 2, y
: bb2
.y
+ bb2
.height
+ off2
}, /* SOUTH 2 */
39 {x
: bb2
.x
- off2
, y
: bb2
.y
+ bb2
.height
/ 2}, /* WEST 2 */
40 {x
: bb2
.x
+ bb2
.width
+ off2
, y
: bb2
.y
+ bb2
.height
/ 2} /* EAST 2 */
43 /* distances between objects and according coordinates connection */
47 * find out the best connection coordinates by trying all possible ways
49 /* loop the first object's connection coordinates */
50 for (var i
= 0; i
< 4; i
++) {
51 /* loop the seond object's connection coordinates */
52 for (var j
= 4; j
< 8; j
++) {
53 var dx
= Math
.abs(p
[i
].x
- p
[j
].x
),
54 dy
= Math
.abs(p
[i
].y
- p
[j
].y
);
55 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
))) {
57 d
[dis
[dis
.length
- 1].toFixed(3)] = [i
, j
];
61 var res
= dis
.length
== 0 ? [0, 4] : d
[Math
.min
.apply(Math
, dis
).toFixed(3)];
67 dx
= Math
.max(Math
.abs(x1
- x4
) / 2, 10),
68 dy
= Math
.max(Math
.abs(y1
- y4
) / 2, 10),
69 x2
= [x1
, x1
, x1
- dx
, x1
+ dx
][res
[0]].toFixed(3),
70 y2
= [y1
- dy
, y1
+ dy
, y1
, y1
][res
[0]].toFixed(3),
71 x3
= [0, 0, 0, 0, x4
, x4
, x4
- dx
, x4
+ dx
][res
[1]].toFixed(3),
72 y3
= [0, 0, 0, 0, y1
+ dy
, y1
- dy
, y4
, y4
][res
[1]].toFixed(3);
73 /* assemble path and arrow */
74 var path
= ["M", x1
.toFixed(3), y1
.toFixed(3), "C", x2
, y2
, x3
, y3
, x4
.toFixed(3), y4
.toFixed(3)].join(",");
76 if(style
&& style
.directed
) {
77 /* magnitude, length of the last path vector */
78 var mag
= Math
.sqrt((y4
- y3
) * (y4
- y3
) + (x4
- x3
) * (x4
- x3
));
79 /* vector normalisation to specified length */
80 var norm = function(x
,l
){return (-x
*(l
||5)/mag
);};
81 /* calculate array coordinates (two lines orthogonal to the path vector) */
83 {x
:(norm(x4
-x3
)+norm(y4
-y3
)+x4
).toFixed(3), y
:(norm(y4
-y3
)+norm(x4
-x3
)+y4
).toFixed(3)},
84 {x
:(norm(x4
-x3
)-norm(y4
-y3
)+x4
).toFixed(3), y
:(norm(y4
-y3
)-norm(x4
-x3
)+y4
).toFixed(3)}
86 path
= path
+ ",M"+arr
[0].x
+","+arr
[0].y
+",L"+x4
+","+y4
+",L"+arr
[1].x
+","+arr
[1].y
;
88 /* function to be used for moving existent path(s), e.g. animate() or attr() */
90 /* applying path(s) */
91 edge
.fg
&& edge
.fg
[move]({path
:path
})
92 || (edge
.fg
= selfRef
.path(path
).attr({stroke
: style
&& style
.stroke
|| "#000", fill
: "none"}).toBack());
93 edge
.bg
&& edge
.bg
[move]({path
:path
})
94 || style
&& style
.fill
&& (edge
.bg
= style
.fill
.split
&& selfRef
.path(path
).attr({stroke
: style
.fill
.split("|")[0], fill
: "none", "stroke-width": style
.fill
.split("|")[1] || 3}).toBack());
97 && (edge
.label
&& edge
.label
.attr({x
:(x1
+x4
)/2, y:(y1+y4)/2})
98 || (edge
.label
= selfRef
.text((x1
+x4
)/2, (y1+y4)/2, style
.label
).attr({fill
: "#000", "font-size": style
["font-size"] || "12px"})));
99 style
&& style
.label
&& style
["label-style"] && edge
.label
&& edge
.label
.attr(style
["label-style"]);
100 style
&& style
.callback
&& style
.callback(edge
);
106 //Raphael.prototype.set.prototype.dodo=function(){console.log("works");};