JavaScript: автоматически упорядочивает переменный многомерный массив по диагонали - PullRequest
7 голосов
/ 29 апреля 2011

Это больше похоже на математический вопрос.

Я пытаюсь создать симпатичный эффект затухания с помощью jQuery, разбивая элемент на определенное количество блоков, затем затухая каждый из них, но задерживаяэффект затухания, основанный на другом массиве.

Итак, для создания таблицы блоков у меня есть две переменные:

var rows = 4,
    cols = 10;

Это разделит элемент на блоки, такие как:

              0   1   2   3   4   5   6   7   8   9
             10  11  12  13  14  15  16  17  18  19
             20  21  22  23  24  25  26  27  28  29
             30  31  32  33  34  35  36  37  38  39

Затем я создаю другой массив, который решает, как блоки будут анимироваться.Например, для диагональной анимации слева направо этот массив будет выглядеть так:

order = [0, 10, 1, 20, 11, 2, 30, 21, 12, 3, 31, 22, 13, 4, 32, 23, 14, 5, 33, 24, 15, 6, 34, 25, 16, 7, 35, 26, 17, 8, 36, 27, 18, 9, 37, 28, 19, 38, 29, 39];

, и для этого конкретного случая он работает: D

Мой вопрос заключается в том, как я могу создатьorder Массив автоматически, а не вручную, в зависимости от количества блоков (строк х столбцов), которые можно изменить?

Спасибо

Ответы [ 3 ]

4 голосов
/ 29 апреля 2011

Это будет сделано:

var arr = [];

var rows = 4;
var cols = 10;

for(var i = 0; i < rows + cols - 1; i++){

    for(var j = Math.min(rows, i + 1) - 1; j >= Math.max(0, i - cols + 1); j--){
        arr.push((j * cols) + i - j);
    }  

}

скрипка: http://jsfiddle.net/BmXpy/

РЕДАКТИРОВАТЬ: Вот моя попытка объяснить, как я пришел к этому.ВАЖНО, используйте приведенную выше таблицу чисел для визуализации и, если необходимо, распечатайте ее и вытяните диагонали.

Сначала подумайте о том, что мы хотим, это в основном диагонали.В приведенном выше примере первая диагональ равна 0, затем 10, 1, затем 20, 11, 2, затем 30, 21, 12, 3 и т. Д. Теперь, если подумать, сколько таких диагоналей, то это rows + cols - 1.Вот где мы получаем первый цикл:

for(var i = 0; i < rows + cols - 1; i++){

Теперь, на секунду игнорируем границы.В общем случае (весь центр) каждая из этих диагоналей имеет длину «рядов».И поскольку мы хотим идти снизу вверх, нам нужен обратный цикл.Это будет выглядеть так для внутреннего цикла:

for(var j = rows - 1; j >= 0; j--){

Теперь мы должны иметь дело с обеими границами (левой и правой).

Для левой границы, если мы посмотрим на число диагоналей, длина которых меньше «строк», мы увидим, что это rows - 1.И для этих диагоналей мы увидим, что длина каждой составляет i + 1.Следующий внутренний цикл будет обрабатывать общий случай и левую границу:

for(var j = Math.min(rows, i + 1) - 1; j >= 0; j--){

Вы увидите, что для диагонали 0 это будет выполняться один раз, для 1 - дважды и т. Д. И для общего случая(i >= rows) он будет запускать «строки» раз.

Теперь правая граница.Если мы посмотрим, какие диагонали справа короче, чем «строки», мы увидим, что все диагонали больше, чем «cols» (в примере, где cols равен 10, 0 проиндексировано, то есть строка 10 и выше).Замена j >= 0 на j >= Math.max(0, i - cols + 1) приведет к 0 для общего случая и левой границы, но сократится для правой границы.Мы получаем это:

for(var j = Math.min(rows, i + 1) - 1; j >= Math.max(0, i - cols + 1); j--){

И, наконец, фактический расчет числа в каждой локации.i представляет диагональ, а j представляет индекс числа на диагонали j = 0 - это верхнее число, если вы смотрите на опубликованную таблицу чисел.Для j = 0 (верхний ряд чисел) число просто i, для каждой строки ниже вершины нам нужно умножить число на «столбцы», чтобы получить число непосредственно под номером первой строки, затемномер нужно отрегулировать влево.Это делается путем вычитания j, который является номером строки.Поэтому для j = 1 (2-й ряд) нам нужно переместить число влево на единицу (вычесть 1).Таким образом, у нас есть i для горизонтального положения в первом ряду, + (j * cols), чтобы переместить его вниз к соответствующему ряду, а затем -j, чтобы отрегулировать его по диагонали (если вы нарисовали диагонали, отследите это для одного из нихчтобы получить хороший визуальный).Мы получаем это:

(j * cols) + i - j

Соберите все вместе, и вы получите мой окончательный код выше.Надеюсь, это имело смысл.

2 голосов
/ 29 апреля 2011

Еще один способ сделать это.

function diagonalized_block (rows, cols) {
    blocks = [];
    for (var i = 0; i < rows * cols; i++) {
        blocks.push(i);
    }
    blocks.sort(function (a, b) {return a/cols + a%cols - b/cols - b%cols});
    return blocks;
}

Идея проста.Запишите очевидный массив всех блоков, а затем сортируйте по функции блока, который возрастает в том порядке, в котором вы хотите.Эта функция x/cols + x%cols.Который row + ascending error on diagonal + col.Таким образом, вы сначала сортируете вещи по их диагонали, а затем по возрастанию по диагонали.

Для других шаблонов вам нужно будет найти другие функции, которые будут правильно сортировать.(Или написать более сложную функцию сортировки, которая делает именно то, что вы хотите.)

1 голос
/ 29 апреля 2011

Здесь есть другой код http://jsfiddle.net/paska/FhLnu/3/

var rows = 4,
    cols = 10,
    getValue = function(x, y) {
        return (y * cols) + x;
    },
    addValue = function(x, y) {
        $("#arr").append(getValue(x, y) + ", ");
    },
    max = rows + cols - 1,
    updateRow = 0;

for(var i = 0; i < max; i++) {
    if(i >= rows)
        updateRow++;
    for(var x = 0; x <= i; x++) {
        //$("#arr").append(x + " " + (i - x) + "<br />");
        var row = (i - x),
            col = x;
        if(updateRow) {
            row = row - updateRow;
            col = col + updateRow;
        }
        if(col >= cols)
            break;
        if(row >= 0 && col >= 0)
            addValue(col, row);
    }
}

Я знаю, что код @kingjiv работает, я просто хотел добавить еще один способ сделать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...