1

Here's a problem I've been struggling with for quite some time now.

enter image description here

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

enter image description here

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 !

4

1 回答 1

0

在 div 的边界处剪裁线的一种方法是将线转换到 div 的本地坐标系。

假设该线由定义x1, y1, x2, y2并且x2, y2需要被剪裁。

所以首先,将场景移动(-divcenterx, -divcentery). 之后,div 的中心将位于原点:

x1 -= divcenterx
y1 -= divcentery
x2 -= divcenterx
y1 -= divcentery

然后我们需要用矩阵恢复旋转R

R11 = cos(angle)
R12 = sin(angle)
R21 = -sin(angle)
R22 = cos(angle)

x1Unrotated = R11 * x1 + R12 * y1
y1Unrotated = R21 * x1 + R22 * y1
x2Unrotated = R11 * x2 + R12 * y2
y2Unrotated = R21 * x2 + R22 * y2

现在我们可以像您一样执行剪辑了。要剪辑的矩形以原点为中心,并具有原始宽度和高度。

之后,我们必须撤消转换。

x1 = R11 * x1Unrotated + R21 * y1Unrotated + divcenterx
y1 = R12 * x1Unrotated + R22 * y1Unrotated + divcentery
x2 = R11 * x2Unrotated + R21 * y2Unrotated + divcenterx
y2 = R12 * x2Unrotated + R22 * y2Unrotated + divcentery

这是线的最终坐标。

于 2013-06-26T13:18:20.617 回答