2011-11-06 31 views
15

Mục tiêu là tạo bố cục dạng lỏng như hiển thị bên dưới.Thuật toán bố cục dạng rắn giống như

enter image description here

Cho đến nay tôi có một chức năng làm việc moveBox(lastBox, "east") mà theo dõi các chỉ số hàng và cột.

function moveBox(box, where) { 
    switch (where) { 
    case "north": 
     lastTopOffset -= BOX_HEIGHT + BOX_MARGIN; 
     box.style.top = lastTopOffset + 'px'; 
     box.style.left = lastLeftOffset + 'px'; 
     rowIndex -= 1; 
     break; 
    // ...  
    } 

My current code,

(function() { 
    var i, lastBox, 
     MAX_DIVS  = 72, 
     BOX_HEIGHT  = 50, 
     BOX_WIDTH  = 100, 
     BOX_MARGIN  = 5, 
     field   = document.getElementById('fieldPerimeter'), 
     fieldHeight = field.offsetHeight, 
     maxRows  = Math.floor(fieldHeight/(BOX_HEIGHT + BOX_MARGIN)), 
     rowIndex  = 0, 
     colIndex  = 0, 
     lastLeftOffset = 0, 
     lastTopOffset = 0; 

    function moveBox(box, where) { 
    switch (where) { 
     case "north": 
     lastTopOffset -= BOX_HEIGHT + BOX_MARGIN; 
     box.style.top = lastTopOffset + 'px'; 
     box.style.left = lastLeftOffset + 'px'; 
     rowIndex -= 1; 
     break; 

     case "east": 
     lastLeftOffset += BOX_WIDTH + BOX_MARGIN; 
     box.style.top = lastTopOffset + 'px'; 
     box.style.left = lastLeftOffset + 'px'; 
     colIndex += 1; 
     break; 

     case "south": 
     lastTopOffset += BOX_HEIGHT + BOX_MARGIN; 
     box.style.top = lastTopOffset + 'px'; 
     box.style.left = lastLeftOffset + 'px'; 
     rowIndex += 1; 
     break; 

     default: 
     break; 
    } 
    } 

    for (i = 0; i < MAX_DIVS; i += 1) { 
    lastBox = document.createElement('div'); 
    lastBox.className = 'box'; 
    lastBox.innerHTML = i; 
    field.appendChild(lastBox);  

    //delete me 
    if((i + 1) % 2 === 0 || (i + 1)% 3 === 0){ 
     moveBox(lastBox, "east"); 
    } else { 
     moveBox(lastBox, "south"); 
    } 
    //delete me  

// if(rowIndex < maxRows && rowIndex > 0){ 
// if (colIndex % 4 === 0){ 
//  moveBox(lastBox, "south"); 
// } else if (colIndex % 2 === 0){ 
//  moveBox(lastBox, "north"); 
// } else { 
//  moveBox(lastBox, "east"); 
// } 
// } 

    }  
})(); 

gắn thêm divs để một container và sau đó di chuyển nó. Đoạn mã dưới đây cho thấy một phần nỗ lực của tôi để chỉ định thời điểm di chuyển Bắc hoặc Nam. Nhưng tôi đang đấu tranh với việc đạt được bố cục mong muốn.

if  (colIndex % 4 === 0) { moveBox(lastBox, "south"); } 
else if (colIndex % 2 === 0) { moveBox(lastBox, "north"); } 
else       { moveBox(lastBox, "east"); } 
+6

Một đoạn mã, hình ảnh và mã (nhờ Bart Kiers) về một câu hỏi thú vị từ người dùng mới? Upvote. Tôi muốn tất cả người dùng mới có điều này sẽ cho họ. ':)' –

+0

Là cách bạn đã tiếp cận nó một yêu cầu, hoặc chỉ là một trong những bạn đã thử? –

+0

Tôi đã thử các cách tiếp cận khác, tôi đã đăng nó bởi vì tôi nghĩ rằng tôi gần nhưng đầu của tôi phát nổ cố gắng tìm ra thuật toán. Sau đó tôi muốn sử dụng một giá trị ngẫu nhiên để không đi đến miền Bắc hay miền Nam, nhưng bây giờ tôi chỉ cần một số hướng dẫn với một số mã giả. Cảm ơn ông Kiers đã chỉnh sửa. – user1032739

Trả lời

5

enter image description here

đây là fiddle làm việc, http://jsfiddle.net/efortis/zuY74/

Lưu ý tôi đã mã hóa cứng offsetHeight để hoạt động trên fiddle và cũng đã thêm biến số lastMove ở trên cùng.

for (i = 0; i < MAX_DIVS; i += 1) { 
    lastBox = document.createElement('div'); 
    lastBox.className = 'box'; 
    lastBox.innerHTML = i; 
    field.appendChild(lastBox); 

    if (i === 0) { 
     rowIndex += 1; 
    } else { 
     if (colIndex % 4 === 0 && rowIndex < maxRows) { 
     moveBox(lastBox, "south"); 
     lastMove = "south"; 
     } else if (colIndex % 2 === 0 && rowIndex !== 1 && lastMove !== "south") { 
     moveBox(lastBox, "north"); 
     lastMove = "north"; 
     } else { 
     moveBox(lastBox, "east"); 
     lastMove = "east"; 
     } 
    } 
    } 
+0

Tuyệt vời đó chính xác là những gì tôi đang tìm kiếm. Cảm ơn ông Fortis – user1032739

2

Sau đây hoạt động với vị trí lưới thay vì pixel, ý tưởng là bạn có thể chuyển đổi vị trí lưới thành pixel mà không gặp sự cố.

Lưới của tôi khá đơn giản. Phía trên bên trái là (0, 0). Vì vậy, máy của bạn 0 là tại (0, 0), hộp 7 là tại (1, 6) vv

Nếu bạn có maxrows hàng, sau đó các maxrows-1 mục đầu tiên đi vào (0, 0), (0, 1), vv Và mục maxrows đi trong (1, maxrows-1). Các mục maxrows-1 tiếp theo đi theo số (maxrows-1,2), (maxrows-2, 2), v.v. và mục tại 2*maxrows sẽ được chuyển vào (0, 3).

Bạn sẽ có thể tính toán vị trí của mục trong lưới từ số của nó. Giả sử toán số nguyên ở đây.

// xblock treats each two columns as a single entity. 
xblock = itemNo/(maxrows + 1); 
xpos = 2 * xblock; 
ypos = itemNo % (maxrows + 1); 
if (ypos == maxrows) 
{ 
    // this is the last item, so we need to shift it. 
    xpos += 1; 
    ypos = maxrows - 1; 
} 

// Now, turn things upside down if xblock is odd 
if ((xblock % 2) == 1 && ypos != maxrows) 
{ 
    ypos = maxrows - ypos - 1; 
} 

Tại thời điểm này, bạn có vị trí lưới nơi hộp nên đi. Nó sẽ là một vấn đề đơn giản bây giờ để biến vị trí lưới đó thành pixel bằng cách nhân số xpos bởi BOX_WIDTH và thêm bù đắp. Làm tương tự cho yposBOX_HEIGHT.

0

tôi nhận thấy đó là một mô hình lặp đi lặp lại trong cách bố trí: Bắt đầu từ 0

  • hộp di chuyển xuống 6 lần (đạt được vị trí 6) hộp
  • bước đi đúng đắn 2 lần (đạt 8)
  • hộp di chuyển lên 6 lần (đạt 14)
  • di chuyển hộp đúng 2 lần (đạt 16)
  • lặp lại

-

var MOVES_DONE = 0; 
var MOVES_LIMIT = 72; 

/* 
* First define the three movement functions that we will use 
* (right, down and left) 
*/ 
function up(box) { 
    console.log("up"); 
} 

function down(box) { 
    console.log("down"); 
} 

function right(box) { 
    console.log("right"); 
} 

/* 
* Solution 1: 
* Starting from the top-left corner do the necessary moves to complete the 
* layout: 

      --------------------------------- 
     |          | 
     box,    up, right, right, 
     down,    up,   start_over 
     down,    up, 
     down,    up, 
     down,    up, 
     down,    up,  
     down, right, right, 
*/ 

var moves = [down, down, down, down, down, down, right, right, 
      up, up, up, up, up, up, right, right]; 

var len_moves = moves.length; 

while(MOVES_DONE < MOVES_LIMIT) { 
    moves[MOVES_DONE % len_moves](box); 
    MOVES_DONE ++; 
} 

Giải pháp 2 bằng cách sử dụng chức năng chuyển động giống nhau:

/** 
* Create a function that will apply a movement type to a box "times" times 
* For example move(down, 6)(box) will 
* move the box down 6 times if moves_done < moves_limit 
*/ 
function move(move_type_function, times) { 
    return function(box) { 
     for (var i = 0; i < times, i + MOVES_DONE < MOVES_LIMIT; i++) { 
      move_type_function(box); 
     } 
     return i; 
    } 
} 

/** 
* This is a complete cycle of the recurring pattern of the layout assuming that 
* we are starting with the box positioned at the 
*/ 
var moves = [move(down, 6), move(right, 2), move(up, 6), move(right, 2)]; 

while(MOVES_DONE < MOVES_LIMIT) { 
    MOVES_DONE += moves[MOVES_DONE % moves.length](box) 
} 

PS: Tôi đã không thực sự có thời gian để kiểm tra điều này trong một trình duyệt để có thể có một số lỗi :)

Các vấn đề liên quan