Логарифмируем облако тегов :)
Всё написанное вот здесь про несложное формирование облака тегов вполне верно. Однако уже не раз, в том числе и в блоге, я обращал внимание на то, что "линейное" изменение размера тега в зависимости от его частоты встречаемости (рейтинга) не очень хорошо отражает суть дела.
Так, самый распространённый на момент написания сообщения тег встречается в моём блоге 77 раз, после пересчёта размера шрифта в диапазон [8,18] пунктов он отобразится максимальным допустимым размером 18 пунктов. Второй по частоте тег имеет 73 вхождения и получит размер в 17 пунктов, что вполне неплохо. Но уже тег, имеющий всего-навсего 4 вхождения отобразится шрифтом в 9 пунктов, а 27 вхождений, то есть чуть больше трети от максимума, дадут размер целых 12 пунктов, то есть, практически "средний" из всех возможных размеров.
Просто некоторое количество тегов обычно намного популярнее большинства других, а линейный расчёт размера шрифта приводит к тому, что небольшое количество важных тегов визуально теряется на фоне множества мало- и среднераспространённых.
Интуитивно ясно, что шкала зависимости размера шрифта от рейтинга слова должна быть скорее логарифмической, чем линейной, ведь именно логарифмическая шкала исключительно удобна для отображения больших диапазонов значений величин. Кроме того, для многих органов чувств величина ощущения пропорциональна логарифму воздействия. Так что давайте попробуем вывести "эвристическое" логарифмирование для размера тегов.
Предположим, что мы рассчитали линейный размер шрифта $size
и по-прежнему имеем максимальную из частот встречаемости в переменной $max
, частоту встречаемости текущего слова (тега) - в элементе массива $tag['rating']
, а отображение
"логарифмических тегов" зависит от установки настройки "движка" с именем
LOGTAGS
в ненулевое значение. Эта настройка может храниться, например,
в файле конфигурации и быть по умолчанию выключенной:
define ("LOGTAGS","0");
Для пересчёта размеров шрифта по логарифмической шкале вместо линейной напишем следующий фрагмент программы:
if (LOGTAGS) { //Если включена настройка логарифмирования тегов $rating=0; if ($tag['rating']>0) $rating=log($tag['rating']); $size=max(BASEFONT,round($size*$rating/log($max))); }
Натуральный логарифм на PHP пишется именно log
, впрочем, применение десятичного log10
мало что бы изменило.
Этот код нужно выполнять в ветви алгоритма if ($max > 0)
после вычисления обычного линейного размера $size
оператором $size+=...
.
Недостаток приведённого кода - если шаг изменения размеров тега PTSTEP
не равен 1
, то допустимые размеры шрифта могут не соблюдаться из-за дополнительного пересчёта, например, разрешены только 10 и 12 пунктов, а получится 11.
Так что для соблюдения размеров, заданных в PTSTEP
, код придётся дополнить следующим (перед закрывающей фигурной скобкой):
$ost = ($size-BASEFONT)%PTSTEP; if ($ost<>0) $size-=$ost;
Окончательно имеем вот что:
if ($max > 0) { $size += PTSTEP * round ($tag['rating'] * TAGSLEVEL / $max); if (LOGTAGS) { $rating=0; if ($tag['rating']>0) $rating=log($tag['rating']); $size=max(BASEFONT,round($size*$rating/log($max))); $ost = ($size-BASEFONT)%PTSTEP; if ($ost<>0) $size-=$ost; } }
Такое облако понравилось мне гораздо больше на сайтах, где я его поставил. Хотя, надо полагать, логарифмическая шкала становится лучше линейной при достаточно большом количестве тегов и заметном разбросе значений их "рейтинга".
Понять, что именно изменилось, поможет картинка:
Линейное и логарифмическое масштабирование размеров слов в зависимости от частоты встречаемости
На ней видно, что менее популярные слова теперь "проваливаются" по размерам шрифта.
А вот документ Excel, в котором я обсчитал это изменение, прежде чем добавить его в код:
Расчёт линейного и логарифмического размера шрифта в Excel (30 Кб)
P.S. Когда избранная елитка самые популярные теги начинают уж слишком выделяться, а у остальных нет шансов увеличить размер - самое время вернуться к линейной шкале. Так что предусмотрел это в движке блога настройкой.
10.04.2012, 13:07 [11887 просмотров]