RaphaelJS формирует демонстрацию Drag & Drop - PullRequest
4 голосов
/ 02 апреля 2012

Я пытался понять работу этого демо: 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 Ответ

12 голосов
/ 03 апреля 2012

Перед этим для цикла 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.Таким образом, мы проверяем каждую точку на obj1 против каждой точки на obj2.Мы стремимся измерить (вроде) расстояние между теми точками, которые мы находим подходящими для соединения.

// 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

IF

  • у нас есть две точки на одной стороне

    (i == j - 4)

ИЛИ

  • у нас нет 3 и 6, или если мы делаем точку 3, то она находится слева от точки 6

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

  • у нас нет 2 и 7, или если мы делаем точку 2, то она находится справа от точки 6

    ((i! = 2 && j! = 7) || p [i] .x> p [j] .x) &&

  • мы не будемt имеет 0 и 5, или, если мы делаем точку 0, находится выше точки 5

    ((i! = 0 && j! = 5) || p [i] .y> p [j] .y)&&

  • у нас нет 1 и 4, или, если мы делаем точку 1, находится ниже точки 4

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

THEN

  • это соединение действительно, сделайте дешевую меру того, какзакройте точки (dy + dx) и поместите эти допустимые соединения в массив.Мы выберем «самое короткое» расстояние позже.

only if connections

Если тестируемые точки не являются одной из этих противоположных пар, мы измеряем их по-прежнему.Это все, чтобы не дать пути оказаться внутри двух объектов, если мы можем помочь.Первый тест, чтобы увидеть, находятся ли они на одной стороне, это дешевый способ пропустить весь этот противоположный код тестирования.После того, как мы измерили все разрешенные точки, мы выбираем наименьшее dy + dx и используем эти точки, чтобы нарисовать путь.

...