Облако тегов
Сегодня будем рассматривать такую задачку как генерация облака тегов. Мы все конечно ни раз встречали это облако на других сайтах и блогах, но не все задумывались над реализацией этого облака на php. Общие моменты ясны из определения с wiki:
“визуальное представление списка ярлыков (или категорий). Частота упоминаний, поисков, ссылок в интернете с определенного сайта неких слов, терминов, имен, отображается на специальной странице в виде изображения этих слов в формате гиперссылок. Размер изображения тем больше, чем выше релевантность данного слова (термина, имени).”
Релевантность в нашем случае определяется количеством вхождений одного тега в их общую массу.
Учитывая все вышесказанное, весь алгоритм построения облака тегов можно разделить на два этапа:
- Генерация списка пар Тег-Количество вхождений
- Вывод облака с учетом релевантности тегов
Первая задача решается довольно просто с технической точки зрения. Вторая тоже, но здесь возможны вариации.
Ниже приведу небольшой класс, который я написал для генерации облака тегов.
<? class TagsCloud { private $tags; private $font_size_min = 14; private $font_size_step = 5; function __construct($tags) { shuffle($tags); $this->tags = $tags; } private function get_tag_count($tag_name, $tags) { $count = 0; foreach ($tags as $tag) { if ($tag == $tag_name) { $count++; } } return $count; } private function tagscloud($tags) { $tags_list = array(); foreach ($tags as $tag) { $tags_list[$tag] = self::get_tag_count($tag, $tags); } return $tags_list; } private function get_min_count($tags_list) { $min = $tags_list[$this->tags[0]]; foreach ($tags_list as $tag_count) { if ($tag_count < $min) $min = $tag_count; } return $min; } public function get_cloud() { $cloud = Array(); $tags_list = self::tagscloud($this->tags); $min_count = self::get_min_count($tags_list); foreach ($tags_list as $tag=>$count) { $font_steps = $count - $min_count; $font_size = $this->font_size_min + $this->font_size_step * $font_steps; $cloud[] = "<span style='font-size:".$font_size."px'>".$tag."</span>"; } return $cloud; } } ?>
Скачать этот класс можно здесь: tagscloud.php, а работать с этим классом примерно так:
<? $tags = array( 'ajax', 'javascript', 'php', 'dojo', 'ajax', 'jquery', 'seo', 'seo', 'php', 'blog', 'ajax', 'php', 'html', 'css', 'ajax', 'javascript', 'css', 'jquery', 'php', 'smo' ); $mycloud = new TagsCloud($tags); $tags_list = $mycloud->get_cloud(); foreach ($tags_list as $tag) { echo $tag.' '; } ?>
В результате работы этого примера в окне браузера Вы получите следующее:
Второй этап построения облака тегов (вывод облака) заключается в преобразовании показателя релевантности (кол-во вхождений) в размер шрифта результирующей надписи.
В классе я реализовал это следующим образом: в настройках задается минимальный размер шрифта, который соответствует минимальному уровню релевантности (одно вхождение). Все теги с большей релевантностью имеют размер на столько пикселей больше, на сколько больше они имеют вхождений. Шаг изменения можно задавать полем font_size_step, а минимальный размер шрифта полем font_size_min.
Для дальнейшего усовершенствования внешнего вида можно прикрутить облако к небольшому js-скрипту. В результате чего получится такое облако: https://nacmnogo.ru/cloud.html. Подробнее про этот скрипт можно почитать здесь https://habrahabr.ru/blogs/javascript/38264/.
Что ж. У меня все. Удачи!
При такой реализации наличие очень популярного тега приведет к тому, что все остальные теги будут отображены одним шрифтом.
Думал про этот баг, но для решения этой задачи в голову приходит только нелинейная зависимость между размером шрифта и уровнем релевантности. Например логарифм натуральный.
ууу до решения таких задачек мне еще рано. что-нибудь попроще бы, это да…..
Классное облако, эффект 3D поражает. Респектище
Да. Респект чуваку, который написал этот плагин на js
2 mr. Hide: Ну это только звучит сложно. На деле - пара строк
ну…. как знать) я сча думаю как писать свой дорген)
Решается с помощью кластерного анализа. В двух словах: все теги разбиваются на заданные группы (кластеры) в соответствии их частотности. Теги из одной группы отображаются одним шрифтом.
Очень популярный тег попадет в отдельную группу, но остальные группы при этом не пострадают.
Подробнее на английском и реализация:
[ссылка]
Я подобный алгоритм сделал на asp.net, если кому надо - обращайтесь.
Спасибо за линк и за новую тему для размышлений В посте рассмотрен алгоритм K-средних, где известно заранее кол-во кластеров, которые получатся в результате - самое то, для облака тегов. Но все равно хочется попробывать реализовать какой-нибудь алгоритм с другими исходными данными, поэтому постараюсь к этой теме вернуться еще в этом блоге
честно говоря, никогда не задумывался какими методам это достигается)
вот они, азы Веб 2.0
foreach ($tags_list as $tag) {
echo $tag.’ ‘;
}
} - лишнее закрытие…
Спасибо, исправил.
Спасибо, позновательно. Попробую в своей теме использовать это.
Спасибо огромное, с вашего позволения использую это у себя на сайте.
Алгоритм страшный, почему не сделать вот так:
private function tagscloud($tags) {
$tags_list = array();
foreach ($tags as $tag) {
if(!isset($tags_list[$tag])) {
$tags_list[$tag] = 1;
}
else {
$tags_list[$tag] += 1;
}
}
return $tags_list;
}
Работает быстрее и выглядит понятнее.
2 Дмитрий: Лучше на примере показать почему такая версия не будет работать.
Допустим есть 3 слова - Картошка (1), Макароны(2) и Телефон(20). В скобках указано кол-во вхождений.
После преобразования этих чисел в размеры шрифтов с сохранением пропорций мы можем получить 2 слова мелким, почти неразличимым, шрифтом и одно большим шрифтом.
Я как сделать, если при добавлении поста, новости и т.д., в строку через запятую вводить тэги, добавлять в БД, но если совпадения, не предпринимать действий.
А можно пример вбивания тегов в базу, с отрезанием запятулек и грамотным запросом к бд ?
Как-то очень много возни с генерацией тег => кол-во.
Почему бы не воспользоваться функцией array-count-values ([ссылка]).
Тогда всё сведётся к
private function tagscloud($tags) {
return array-count-values(tags);
}
Ну и поиск min/max - оптимально - отсортировать по кол-ву
через asort и взять первый и последний элементы
[…] любого популярного ресурса становится понятие облако тегов или, проще говоря, облако ключевых слов. Любой […]
Будет очень печально, если массив с метками на входе в конструктор окажется большим.
Если записей с популярным тегом будет ооочень много - шрифт будет гигантским - попортит весь дизайн.
имхо необходимо определить также и максимальный размер шрифта. а остальные по 2 путям можно строить:
1. самое большое вхождение = самый большой шрифт
самое маленькое = самый маленький
остальные = пропорционально весу
2. самое маленькое вхождение = самый маленький шрифт
остальные = с шагом
если значение больше макса, то оно приравнивается максу
124214