Как домашняя страница TED Talk организует сетку видео?

Я пытался выяснить, как работает Домашняя страница TED Talk. Оставляя в стороне все мусорные мухи, я нахожу, что организованные коробки действительно увлекательны.

На первый взгляд это выглядит как jQuery masonry plugin, быстро становится понятным, что он имеет тенденцию создавать несколько прямоугольных треугольных фигур, но не имеет фиксированного количества столбцов или строк, и конечная форма, полученная, всегда полностью сплошная (без полых частей).

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

Кто-нибудь знает, как это работает?

Ответ 1

Я думаю, что я это разработал.

Прежде всего, количество элементов существенно меняется, в настоящее время я просматриваю страницу с 13 полями.

Чтобы начать, я назову каждый из четырех размеров блоков от самых больших до самых маленьких: А, В, С, D

Как мы знаем, первая "строка" содержит два As и два вертикальных стека Bs, например:

 _______________________
|   A   | B |   A   | B |
|       |___|       |___|
|       | B |       | B |
|_______|___|_______|___|

Расположение этих элементов представляется случайным, но Bs всегда находятся в одном и том же вертикальном шаблоне. Глядя на это сейчас, я понял, что есть только две строки, а вторая строка работает одинаково.

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

Я нашел 9 из этих шаблонов форм, два из которых являются одиночными A или B, а остальные:

  _______    _______    _______    ___    ___    _______    ___
 | B | B |  |   A   |  | B | B |  |C|C|  | B |  |   A   |  |C|C|
 |___|___|  |       |  |___|___|  | B |  |___|  |       |
 |   A   |  |       |  | B | B |  |___|  |C|D   |       |
 |       |  |_______|  |___|___|                |_______|
 |       |  | B | B |  |   A   |                | B |    
 |_______|  |___|___|  |       |                |___|    
 |B  |C|    |B  |C|    |       |
 |___|      |___|      |_______|

Следующий вопрос: как они выбраны? Может быть какой-то умный поиск, чтобы найти наилучшую конфигурацию: например, если есть элементы X, которые нужно отобразить, нам нужно найти конфигурацию с общим числом X, которое не превышает ширину строки.

Это можно сделать с помощью метрики плотности рисунка, которая будет представлять собой количество блоков, деленное на ширину шаблона.

Ответ 2

Может быть не так, но несколько наблюдений:

  • В каждом разделе есть 19 видеороликов
  • Есть 4 размера 1 (# 1), 1/4 (# 2), 1/16 (# 3) и 1/32 (# 4)

Для данного раздела всегда есть 4 (# 1). Число (# 2), (# 3) и (# 4) может быть:

  • 4 (# 1), 10 (# 2), 4 (# 3), 1 (# 1) = 19
  • 4 (# 1), 11 (# 2), 4 (# 3), 0 (# 1) = 19
  • 4 (# 1), 11 (# 2), 3 (# 3), 1 (# 1) = 19
  • 4 (# 1), 12 (# 2), 2 (# 3), 1 (# 1) = 19
  • 4 (# 1), 13 (# 2), 1 (# 3), 1 (# 1) = 19

Что касается порядка:

  • Первая строка всегда содержит 2 (# 1) и 4 (# 2)
  • (# 4) всегда находятся в нижней части столбца

Ответ 3

Вот код javascript, который делает это (вам нужна html-страница с div#container):

function ted_layout(settings, coordinates_array, num_elements, start_x, start_y, arrangement, remaining_elements, is_child){
    var num_columns = arrangement.length;
    var col = 0;
    var current_x = start_x;
    while( col < num_columns){
        var column_x_scale = 100 / arrangement[col];
        var current_column_arrangement;
        if(is_child){
            if(num_elements > 14){
                if(column_x_scale == 50){
                    current_column_arrangement = random_shuffle([1, 2, 2]);
                } else {
                    current_column_arrangement = random_shuffle([1, 2]);
                }
            } else if(num_elements > 10){
                if(column_x_scale == 50){
                    current_column_arrangement = [1];
                } else {
                    current_column_arrangement = random_shuffle([1, 2]);
                }
            } else{
                    current_column_arrangement = random_shuffle([1, 2]);
            }
        } else {
            if(num_elements > 14){
                if(column_x_scale == 25){
                    current_column_arrangement = [1, 1];
                } else {
                    current_column_arrangement = [1];
                }
            } else if(column_x_scale == 25){
                    current_column_arrangement = [1, 1];
            } else {
                    current_column_arrangement = [1];
            }
        }


        var num_rows = current_column_arrangement.length;
        var current_y = start_y;
        var row = 0;
        while(row < num_rows){

            var numRects = current_column_arrangement[row];
            var current_rectangle = 0;
            var current_rectangle_x = current_x;

            while( current_rectangle < numRects){
                if(remaining_elements == 0){
                   return coordinates_array;
                }
                var currScale = column_x_scale/numRects;
                var height = settings.height * currScale*0.01;
                var width = settings.width * currScale*0.01;
                if(current_rectangle == numRects-1 && row == num_rows-1 && is_child && Math.random() > 0.5){
                    coordinates_array.push({x: current_rectangle_x, y:current_y, w:width/2, h:height/2, scale:currScale/2*0.01*2})
                }
                else{
                    coordinates_array.push({x: current_rectangle_x, y:current_y, w:width, h:height, scale:currScale*0.01*2})
                }
                current_rectangle_x += width;
                remaining_elements--;
                current_rectangle++;
            }
            row++;
            current_y += height;
        }
        current_x = current_rectangle_x;
        col++;
    }
    if( remaining_elements > 0){
        coordinates_array = ted_layout(settings, coordinates_array, num_elements, start_x, current_y, random_shuffle([2, 4, 4, 2]), remaining_elements, true);
    }
    return coordinates_array;
}


function generate_ted_layout(num_elements){
    var settings = {
        width: 640,
        height: 480,
    };
    var coordinates_array=[];
    returned = ted_layout(settings, coordinates_array, num_elements, 0, 0, random_shuffle([2, 4, 4, 2]), num_elements, false);
    console.log("Returned", returned)
    return returned;
}

function random_shuffle(array){
    var temp;
    for(var i = array.length - 1; i >= 1; i--){
        var elem = Math.floor(Math.random() * (i + 1));
        temp = array[elem];
        array[elem] = array[i];
        array[i] = temp;
    }
    return array;
}


function initAndLayout() {
    var items = generate_ted_layout(20);

    var container = $('#container');    // cache jquery object
    console.log(items);
    for (var i = 0; i < items.length; i++)
    {
        var item = items[i];
        console.log(item);
        $('#container').append($('<div class="item"></div>').css({'left': item.x, 'top': item.y, 'width': item.w, 'height': item.h}));
    }
}