В каталоге партнёров СберСпасибо 4 800 карточек одинаковой высоты, разложенных сеткой. На широком экране в строке 5 карточек, на телефоне — 2. Рендерить все 4 800 нельзя: страница тормозит при прокрутке.
Напишите gridRange({ count, width, minItemWidth, rowHeight, scrollTop, viewport, buffer }). Колонок columns = max(1, floor(width / minItemWidth)), строк ceil(count / columns), полная высота rows · rowHeight.
scrollTop сначала ограничьте отрезком [0, max(0, totalHeight − viewport)]. Видимые строки — от floor(scrollTop / rowHeight) до ceil((scrollTop + viewport) / rowHeight) не включая; к ним добавьте buffer строк сверху и снизу, не выходя за [0, rows].
Верните { columns, start, end, offsetY, totalHeight }: start, end — индексы карточек (end не включая, не больше count), offsetY — сдвиг первой отрисованной строки в пикселях. Пустой каталог — нули и columns по ширине.
В работе: Каталог на 4 800 карточек: на экране помещается 15, а в DOM должно быть не больше 40 с запасом на быструю прокрутку.
Пример 1: верх каталога, 5 колонок
{"count": 4800, "width": 1200, "minItemWidth": 230, "rowHeight": 280, "scrollTop": 0, "viewport": 800, "buffer": 2}{"columns": 5, "start": 0, "end": 25, "offsetY": 0, "totalHeight": 268800}Пример 2: середина каталога
{"count": 4800, "width": 1200, "minItemWidth": 230, "rowHeight": 280, "scrollTop": 28000, "viewport": 800, "buffer": 2}{"columns": 5, "start": 490, "end": 525, "offsetY": 27440, "totalHeight": 268800}gridRange — тест вызывает её сам. Таймеры и Date в тестах ненастоящие: время идёт по команде теста, поэтому setTimeout на 5 секунд проверяется мгновенно. Тестов 9: 2 открыты выше, остальные приходят после старта подхода. Лимит — 2 с на тест.
function gridRange({ count, width, minItemWidth, rowHeight, scrollTop, viewport, buffer }) // → { columns, start, end, offsetY, totalHeight }
Источник: на задачах Сбера: каталог партнёров СберСпасибо. Условие пересказано своими словами.
Ожидаемый ответ не нужен: покажем, что вернула функция.
Здесь появится результат отправки.