RaphaelJS塑造Drag& Drop演示

时间:2012-04-02 16:48:41

标签: javascript raphael

我试图理解这个演示的工作:http://raphaeljs.com/graffle.html 但我无法理解graffle.js源代码中的这个循环:

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];
        }
    }
}

任何人都可以向我解释它的作用及其运作方式吗?感谢。

1 个答案:

答案 0 :(得分:12)

在此for循环之前,构造一个单独的数组,其中包含路径可以从中加入的每个对象的4个位置。

var bb1 = obj1.getBBox(),
    bb2 = obj2.getBBox(),
    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}],

所以你有2个对象obj1和obj2想要与路径连接在一起。必须将路径绘制到对象边缘上4个可能点中的任何一个点:

path positions

我根据p中的索引标记了顶点。现在我们将循环遍历obj1上的点和obj2上的点,使用i作为obj1上的点的索引,使用j作为obj2上的点的索引。这样我们就obj2上的每个点测试obj1上的每个点。我们的目标是测量(排序)我们认为适合连接的那些点之间的距离。

// For each pair of adjacent points
for (var i = 0; i < 4; i++) {
    for (var j = 4; j < 8; j++) {

        // Calculate the difference in the X and Y direction (dy and dx)
        var dx = Math.abs(p[i].x - p[j].x),
            dy = Math.abs(p[i].y - p[j].y);

             // If the points are on the same side  OR  
        if ((i == j - 4) || 
            // If the points are **not** opposites (3 and 6) or (2 and 7) or (0 and 5) or (1 and 4) 
            // or, if we have 3 and 6, and the obj1 is to the left side of obj2
            // or, if we have 2 and 7, and the obj1 is to the right side of obj2
            // or, if we have 0 and 5, and the obj1 is higher than obj2
            // or, if we have 1 and 4, and the obj1 is lower than obj2

            (((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))) {
            // push the sum of dx and dy onto out distance list
            // and push the associated pair of points onto the d list.
            // This is so we can pick the sort-of-closest pair of points.
            dis.push(dx + dy);
            d[dis[dis.length - 1]] = [i, j];
        }
    }
}

所以要打破那个大的if语句

如果

  • 我们在同一方面有两点

    (i == j - 4)

OR

  • 我们没有3和6,或者如果我们在第6点的左边做第3点谎言

    ((i!= 3&amp;&amp; j!= 6)|| p [i] .x&lt; p [j] .x)&amp;&amp;

  • 我们没有2和7,或者如果我们做点2位于第6点右侧

    ((i!= 2&amp;&amp; j!= 7)|| p [i] .x&gt; p [j] .x)&amp;&amp;

  • 我们没有0和5,或者如果我们点0位于第5点之上

    ((i!= 0&amp;&amp; j!= 5)|| p [i] .y&gt; p [j] .y)&amp;&amp;

  • 我们没有1和4,或者如果我们点1点位于第4点以下

    ((i!= 1&amp;&amp; j!= 4)|| p [i] .y&lt; p [j] .y)

THEN

  • 这个连接是有效的,对点的接近程度(dy + dx)做一个便宜的测量并将这些有效的连接放在一个数组中。我们稍后会选择“最短”​​距离。

only if connections

如果测试的点不是这些相对的点之一,那么我们仍然测量它。如果我们可以帮助它,这就是阻止路径进入2个对象的全部内容。第一个测试它们是否在同一侧的测试是一种廉价的方法来跳过所有这些相反的测试代码。在我们测量了所有允许的点之后,我们选择最小的dy + dx并使用这些点绘制路径。