Here's a problem I've been struggling with for quite some time now.
As you can see this is the current state of the problem that actually works. I drag a line between 2 divs with a tool and the arrow follows the rectangle bounds either if I move the source div or the destination div. To do so, I calculate the intersection between the line (defined by 2 points that represent center of each div) and the bound of the rectangle.I, then, reduce the line by getting the distance between the center of the destination div and its bound. So far so good.
Here's the tricky part : I recently implemented the ability to rotate those rectangles like so
And there are two problems:
- When you drag a line from a rectangle (not rotated) to a rotated one, it still follow the bounds like it wasn't rotated
- When you drag a line from the rotated rectangle to another, it doesn't stick to the other rectangle's bound
So my question is : How do I make these arrows to follow rotated rectangles. Trickier, how to draw an arrow for a rotated rectangle to another rotated one. I'm restricted in technologies I can use : HTML5,CSS3,JQuery(Javascript) No HTML5 canvas can be used.
I have the rotation angle of the rectangle since I set it myself.
Here's my code to calculate Intersection point, hypothenuse(arrow width) and rotation angle of the line :
var link = $(target).find(".arrow");
if ($(link).length) {
$.each(link, function (index, value) {
/* zoomLevel is just a scaling of the container, it corrects position but here, you can just ignore it */
var x1 = $(target).offset().left + ($(target).width() / 2) * zoomLevel;
var y1 = $(target).offset().top + ($(target).height() / 2) * zoomLevel;
var to = $(value).attr("data-bind");
var destinationStuff = $("body").find("#" + to);
var destinationW = ($(destinationStuff).width() / 2) * zoomLevel;
var destinationH = ($(destinationStuff).height() / 2) * zoomLevel;
var x2 = $(destinationStuff).offset().left + destinationW;
var y2 = $(destinationStuff).offset().top + destinationH;
var hypotenuse = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
var angle = Math.atan2((y1 - y2), (x1 - x2)) * (180 / Math.PI);
angle += 180;
var a = (y2 - y1) / (x2 - x1);
var minushyp = 0;
if (-destinationH <= a * destinationW && a * destinationW <= destinationH) {
if (x1 > x2) {
//intersect with left side target
interX = Math.abs(a * destinationW);
minushyp = Math.sqrt((destinationW) * (destinationW) + (interX) * (interX));
} else {
//intersect with right side target
interX = Math.abs(a * destinationW);
minushyp = Math.sqrt((destinationW) * (destinationW) + (interX) * (interX));
}
} else if (-destinationW <= destinationH / a && destinationH / a <= destinationW) {
if (y1 > y2) {
//intersect with bottom side target
interX = Math.abs(destinationH / a);
minushyp = Math.sqrt((destinationH) * (destinationH) + (interX) * (interX));
} else {
//intersect with top side target
interX = Math.abs(destinationH / a);
minushyp = Math.sqrt((destinationH) * (destinationH) + (interX) * (interX));
}
}
animateBind(value, target, hypotenuse, minushyp, angle, false);
});
}
And I have a function that does the same think but when you drag a destination rectangle (so every arrows that are bound to it move as well)
and some HTML
<div class="board">
<div class="stuffSet object" id="box5" data-rotation="20"
style="top: somepx; left: somepx; -webkit-transform-origin:0% 0%; -webkit-transform:rotate(some degrees)">
<div class="stuffSet object" id="box4" style="top: 220px; left: 702px;">
<div class="subStuff arrow object" data-bind="box5">
<div class="line top left" style="border-width: 1px; right: 0px;"></div>
<div class="line top right" style="border-width: 1px; right: 0px;"></div>
<div class="line center" style="border-width: 1px;"></div>
</div>
</div>
</div>
Every think is absolutely positioned in the board Thanks !