Pull to refresh

Алгоритм «газетной» вёрстки web-страницы

Reading time3 min
Views1K
Сей пост специально пишу в личный блог, дабы не засорять общие.

На работе встала задачка: есть энное количество статей, возможно, с картинками, и просто картинок, и эту кучку добра надо автоматически заверстать на веб-страницу в формате газеты — т.е., в несколько колонок, одну статью в одну колонку, другую — в три, но по высоте меньше. И ещё все картинки вписать в колонки, чтобы смотрелось точь-в-точь как разворот газеты.
Мне почему-то не хочется верить, что я первый, кто столкнулся с такой задачей. Это не отменяет того, что я уже примерно представляю себе алгоритм ;) Но тем не менее, хотелось бы услышать тех, кто уже сталкивался с такой задачей. Или просто тех, кому задача показалась интересной. Да кого, угодно, на самом деле =)

Приступим.

0) Исходные данные
Допустим, у нас некий набор статей\картинок. В каждой статье тоже могут (но не обязаны) быть изображения. Есть ширина газетного листа страницы, допустим 1000px. И есть количество колонок, на которые надо эту страницу поделить.

Общая идея:
Страница делится на «квадраты» (некий аналог попугаев из известного мульта). Т.е. если у нас пять колонок, то ширина колонки — 200px, и высота квадратика, соответственно, тоже 200 px. В итоге получаем прямоугольник 5 квадратов в ширину и бесконечность в высоту. Затем идёт просчёт всех различных вариантов размеров контента — допустим, одну и ту же статью можно сделать как размера 1х4 квадрата, так и 2х2, так и 4х1 — т.е. по площади одинаково. Но следует оглядываться на два тонких момента:
а) Если в статье есть картинки, то их нужно ресайзить\кропать, делая её ширину кратной ширине колонки, и только затем уже считать общую площадь;
б) Считать площадь, занимаемую текстом, надо, ОБЯЗАТЕЛЬНО отталкиваясь от ширины символов шрифта — иначе мы рискуем «доокругляться» со всевозможными переносами слов.
В результате, после всех рассчётов, мы имеем набор элементов с вариациями их размера, которые нужно оптимальным образом вписать в прямоугольник с фиксированной шириной — это уже не проблема. Хоть простейшим перебором вариантов =) Затем полученный результат (между прочим, может быть и не одно оптимальное расположение, тогда можно отдавать рандомом какое-то из них) кэшируем и пользователю отдаём уже статичный хтмльник, в котором статьи находятся в дивах с жёстко заданными размерами в пикселях. При поступлении новой статьи\картинки — и р-раз, и два, и три — на исходную! — повторяем процедуру.

Резюмируя, краткий алгоритм:
1. Рассчёт вариантов площадей статей, изображений в них и «stand-alone» изображений;
2. Выбор оптимальн(ого\ых) вариант(а\ов) расположения.

Выглядит не особо сложно, но хочется (в том числе и для себя) проговорить основные моменты.

1) Отдельные изображения
Это те, которые не в статье, а просто картинки. С ними, по-моему, проще всего — мы их либо ресайзим, либо кропаем до нужной нам ширины, высота остаётся пропорциональной.
Есть, кстати, ещё идейка (на будущее) — раз уж хочется полного сходства с газетой, можно писать заголовки на картинках (используя гд, к примеру). Но это я отвлёкся, это всё когда-нибудь потом, да и то не факт =)

2) Шрифты
Похоже, что без значений ширины символов шрифта не обойтись — иначе не получится рассчитать объём статьи. Следовательно, нужна функциональность работы со шрифтами — допустим, некая серверная тулза, запускаемая пхпшным exec'ом, или парсер .ttf файлов, неважно. Это уже детали реализации, но все значения ширины символов шрифты должны лежать в базе (её пнуть явно быстрее, чем парсер).

3) Изображения в статьях
Занимают определённую площадь. Пока что придерживаюсь мнения, что их стоит загонять в угол, а затем вставлять текст и считать общую площадь в «квадратах». Опять же, изображение можно растянуть на разное количество квадратов, так что здесь тоже возможны варианты.
Также не стоит забывать, что изображений может быть много. В этом случае пока затрудняюсь… Надо ещё подумать. Идеи принимаются.

4) Поиск оптимального варианта расположения
Не вижу ничего затруднительного — перебор всех вариантов расположения всех вариантов элементов, и, собственно, вуаля.

Так вот, возвращаясь к — зачем же я это написал.
Очень хочется услышать какие-либо советы, подсказки и прочие подобные штуки. Взамен обещаю, когда всё будет готово (а оно будет, это точно), выложить линк для общественности.
Если вдруг найдётся кто-то, кто сталкивался с подобной задачей — этот человек будет для меня на вес золота ;)
Да и вообще… Согласитесь, задачка нетривиальная? ;) А мозг размять всегда интересно. Лично я, по крайней мере, рад этому проекту — если я мыслю, значит, я существую =)
Так или иначе, спасибо всем, кто осилил этот текст. Я старался писать максимально понятно, но если у меня не получилось — отвечу на любой вопрос по существу в комментах.
Tags:
Hubs:
+8
Comments23

Articles

Change theme settings