2011-04-29 20 views
7

Esto es más como una pregunta relacionada con las matemáticas.JavaScript: ordena automáticamente una matriz multidimensional variable diagonalmente

Estoy tratando de crear un lindo efecto de desvanecimiento con jQuery, dividiendo un elemento en un cierto número de bloques, luego desvaneciendo cada uno de ellos, pero demorando el efecto de desvanecimiento basado en otra matriz.

Así que para crear la tabla de bloques Tengo dos variables:

var rows = 4, 
    cols = 10; 

Esto dividirá el elemento en bloques como:

   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 

Entonces estoy creando otra matriz que decide cómo los bloques animará. Por ejemplo, para una animación en diagonal de izquierda a derecha esta matriz se vería así:

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

y para este caso específico funciona: D

Mi pregunta es ¿cómo podría crear la matriz order de forma automática, no de forma manual, en función del número de bloques (filas x columnas), que puede cambiar?

Gracias

+0

¿Siempre sería para animación diagonal de izquierda a derecha? – Diego

+0

no, también quiero hacer esta diagonal r-t-l, o rotar desde el centro, etc. Pero por ahora me gustaría entender cómo puedo hacer esto en este caso, l-t-r diagonal – Alexandra

Respuesta

4

Esto lo hará:

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

} 

violín: http://jsfiddle.net/BmXpy/

EDIT: Aquí está mi intento de explicar la forma en que se me ocurrió esto. IMPORTANTE: utilice la tabla de números anterior para visualizar y, si es necesario, imprimirlo y dibujar las diagonales.

Primero, piense en lo que queremos, es básicamente diagonales. En el ejemplo anterior, la primera diagonal es 0, luego 10, 1, luego 20, 11, 2, luego 30, 21, 12, 3, etc. Ahora, si piensas cuántas de esas diagonales hay, es rows + cols - 1. Ahí es donde obtenemos el primer ciclo:

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

Ahora, ignore por un segundo los límites. En el caso general (todo el centro), cada una de estas diagonales tiene "filas" largas. Y como queremos ir hacia abajo, queremos un ciclo inverso. Que se vería así para el bucle interno:

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

Ahora, tenemos que hacer frente a ambos limites (izquierda y derecha).

Para el límite izquierdo, si miramos el número de diagonales que son menos que "filas" de largo, veremos que es rows - 1. Y para estas diagonales veremos que la longitud de cada una es i + 1. El siguiente bucle interno manejará el caso general y el sitio limítrofe izquierda:

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

Usted verá que para diagonal 0, este se ejecutará una vez, durante 1 se ejecutará dos veces, etc, y para el caso general (i >= rows) ejecutará "filas" veces.

Ahora, la boundry correcta. Si miramos qué diagonales de la derecha son más cortas que "filas", veremos que todas las diagonales son mayores que "cols" (en el ejemplo donde cols está indexado en 10, 0, es decir, en la fila 10 y más adelante).Reemplazando j >= 0 con j >= Math.max(0, i - cols + 1) se ejecutará a 0 para el caso general y el límite izquierdo, pero se acortará para el límite derecho. Obtenemos esto:

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

Y, por último, el cálculo real del número en cada ubicación. i representa la diagonal y j representa el índice del número en la diagonal j = 0 es el número superior si está mirando la tabla de números publicada. Para j = 0 (fila superior de números) el número es simplemente i, para cada fila debajo de la parte superior, necesitamos multiplicar el número por "cols" para obtener el número directamente debajo del número de la primera fila, luego el número debe ser ajustado a la izquierda. Esto se hace restando j que es el número de fila. Entonces, para j = 1 (la 2da fila) necesitamos mover el número que queda en uno (restar 1). Entonces tenemos i para la posición horizontal en la primera fila, + (j * cols) para moverlo a la fila apropiada y luego -j para ajustarlo a diagonal (si ha dibujado las diagonales, trace esto para una de ellas para obtener una buena visual). Obtenemos esto:

(j * cols) + i - j 

Ponlo todo junto y obtienes mi código final anterior. Espero que tenga algo de sentido.

+0

Brillante ... ¡¡Demasiado bueno !! –

+0

@kingjiv: muy agradable! Por cierto, se recomienda utilizar '[]' en lugar de 'Array()' – Diego

+0

¡hermoso! pero por favor explícame eso, estoy completamente perdido después de 'i Alexandra

1

Aquí hay otro código 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); 
    } 
} 

Sé que funciona @kingjiv código, sólo quería añadir otra forma de hacerlo.

2

Otra forma de hacerlo.

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

La idea es simple. Escriba la matriz obvia de todos los bloques y luego ordene por una función del bloque que está ascendiendo exactamente en el orden que desee. Esa función es x/cols + x%cols. Cuál es row + ascending error on diagonal + col. Entonces ordena primero las cosas por la diagonal en la que se encuentran y luego asciende en la diagonal.

Para otros patrones, deberá encontrar otras funciones que se clasifiquen correctamente. (O escriba una función de clasificación más complicada que haga exactamente lo que usted quiere que haga).

Cuestiones relacionadas