ASP.NET MVC: История одного проекта Облако тегов (часть 11)
Содержание
ASP.NET MVC: История одного проекта "Готовимся к старту" (часть 1)
ASP.NET MVC: История одного проекта "Всё ради данных" (часть 2)
ASP.NET MVC: История одного проекта "Шаблоны и внешний вид" (часть 3)
ASP.NET MVC: История одного проекта "Еще немного классов" (часть 4)
ASP.NET MVC: История одного проекта "UI - всё для пользователя" (часть 5)
ASP.NET MVC: История одного проекта "UI - Добавление экспоната" (часть 6)
ASP.NET MVC: История одного проекта "UI - Редактирование экспоната" (часть 7)
ASP.NET MVC: История одного проекта "Обработка ошибок" (часть 8)
ASP.NET MVC: История одного проекта "Фильтрация" (часть 9)
ASP.NET MVC: История одного проекта "Поиск" (часть 10)
ASP.NET MVC: История одного проекта "Облако тегов" (часть 11)
ASP.NET MVC: История одного проекта "Главная страница" (часть 12)
Тема дня
Облако тегов очень удобный и распространный вариант навигации по сайту. Тема этой части - "Облако меток" (или облако тегов, если хотите, или вообще, облако ключевых слов).
Предмет разговора
Экспонаты в музее юмора помечаются метками, а значит эти метки можно представить пользователю в виде облака. Облако буду делать с разбиением на группы (кластеры), чтобы оно наглядно отображало частоту использования меток, отображая часто используемы большим размеров, а малоспользуемые, соответственно, меньшим.
Кластерный анализ
Итак, приступим. У меня на сайте в музее очень большое количество меток. Для того чтобы сформировать "правильное" облако меток, воспользуюсь методом кластерного анализа. Этот алгоритм достаточно прост, и для достижения успешного результата надо:
- Задать количиство групп (кластеров)
- Определить центр масс для каждой группы. Это обычное число, по которому выполняется разбиение. В моем случае это частота использования тега. Минимальное количество я задал для первой группы, а максимальное количество, соответственно, для последней 10-ой группы.
- Определить расстояние от центра массы до тега для каждой метки. Это простое арифметическое вычитание из количества использования метки числа центра масс .
- Сгруппировать метки в в группы (кластеры). Требуется найти какой центр масс ближе числу использований метки. В эту группу и добавляем метку.
- Пересчитываем значения центров масс. На этом этапе надо определить среднее значение частоты использования всех тегов, которые вошли в группу (кластер) в пункте 4.
- Повторяем пункты с 3-го по 5-ый, пока не закончатся метки.
Описаный процесс можно узреть на блок-схеме:
Я определю в своем облаке 10 групп (кластеров). У меня кластеры (группы) будут отображаться разными CSS стилями. Таким образом, у меня будет для каждой из групп задан свой стиль в CSS. Определения стилей показывать не буду, пусть каждый раскрасит метки в зависимости от "частоты" самостоятельно.
Класс TagCloud
Для начала создаю класс, который будет использоваться при формировании облака меток:
/// <summary> /// Класс тега для облака. /// </summary> public class TagCloud { #region конструкторы public TagCloud() { } public TagCloud(string name, string css, int total) { this.Name = name; this.CssClass = css; this.Total = total; } public TagCloud(int id, string name, string css, int total) { this.Id = id; this.Name = name; this.CssClass = css; this.Total = total; } #endregion #region свойства /// <summary> /// Идентификатор /// </summary> public int Id { get; set; } /// <summary> /// Наименование /// </summary> public string Name { get; set; } /// <summary> /// Стиль Css /// </summary> public string CssClass { get; set; } /// <summary> /// Всего изпользован /// </summary> public int Total { get; set; } #endregion }
Формирование облака
Надеюсь всё понятно, со свойствами и с конструкторами класса TagCloud. Теперь надо сделать расширение (extension), которое будет метки (tag) превращать в метку для облака (TagCloud):
internal static IEnumerable<TagCloud> TagsToCloudItems(this IEnumerable<Tag> source) { if (source == null) throw new ArgumentNullException("source"); return source.Select(x => new TagCloud(x.Id, x.Name, "tag", x.Exhibits.Count)); }
Следующим этапом требуется создать расширение (extension), которое разобъёт сформированные метки для облака (TagCloud) по группам (в кластеры). Приведу этот код целиком:
/// <summary> /// Создает облако тегов /// </summary> /// <param name="tagsCloud">Массив меток</param> /// <param name="clusterCount">Количество кластеров при генерации</param> internal static IEnumerable<TagCloud> CreatorCloud(this IEnumerable<TagCloud> tagsCloud, int ClusterCount) { int totalCount = tagsCloud.Count(); tagsCloud = tagsCloud.OrderBy(ff => ff.Total).ToArray(); List<List<TagCloud>> clusters = new List<List<TagCloud>>(); if (totalCount > 0) { int min = tagsCloud.Min(c => c.Total); int max = tagsCloud.Max(c => c.Total) + min; int completeRange = max - min; double groupRange = (double)completeRange / (double)(ClusterCount); List<TagCloud> cluster = new List<TagCloud>(); double currentRange = min + groupRange; for (int i = 0; i < totalCount; i++) { while (tagsCloud.ToArray()[i].Total > currentRange) { clusters.Add(cluster); cluster = new List<TagCloud>(); currentRange += groupRange; } cluster.Add(tagsCloud.ToArray()[i]); } clusters.Add(cluster); } TagCloud tc; List<TagCloud> result = new List<TagCloud>(); for (int i = 0; i < clusters.Count; i++) { foreach (TagCloud item in clusters[i]) { tc = new TagCloud(item.Id, item.Name, "tag" + i.ToString(), item.Total); result.Add(tc); } } return result.OrderBy(x => x.Name).AsEnumerable(); }
Можно было бы сделать всё в одном методе: и превращение меток в облачные метки, и сразу же разбросать их по группам. Но я специально разделил на два метода. Первый будет использоваться в WCF-сервисе для Silverlight. Далее в контролере Museum создаем новый ActionResult:
[OutputCache(Duration = 2880)] public ActionResult Cloud() { var model = tagRepository .AllIncluding(x => x.Exhibits) .TagsToCloudItems() .CreateCloud(10); return View(model); }
Просто последовательно вызываю два расширения на коллекцию меток (Tag), и затем отдаю их в представление (View). Обратите внимание на то, что я пометил данный метод аттрибутом OutputCache, который на 48 часов будет кэшировать данные выдаваемые в результате выполнения этого метода. Это сделано в силу того, что частота обновления облака не велика.
UI облака
Если есть метод Cloud значить должно быть и представление (View). В этом представлении подключаю дополнительный CSS для отображения меток по группам кластера, о котором я говорил выше. А отрисовку меток делает UserControl (выделено жирным):
@section header{ <link href="@Url.Content("/content/tags.css")" rel="stylesheet" type="text/css" /> } @model IEnumerable<Calabonga.Mvc.Humor.Models.TagCloud> @{ ViewBag.Title = "Облоко тегов"; Layout = "~/Views/Shared/_LayoutMain.cshtml"; } <h2> Облако меток музейных экспонатов</h2> <p>@Html.Partial("Controls/TagCloudControl")</p>
И сам контрол для отрисовки меток:
@model IEnumerable<Calabonga.Mvc.Humor.Models.TagCloud> @if (Model != null && Model.Count() > 0) { foreach (Calabonga.Mvc.Humor.Models.TagCloud item in Model) { <span style="margin: 2px; padding: 2px; line-height: 2em; background-color: #f5f5f5;"> @Html.ActionLink( string.Concat(item.Name, " (", @item.Total, ")"), "index", "museum", new { t = item.Name }, new { @class = item.CssClass }) </span> } }
Запускаем... Хм... Ссылки-то на облако меток нет... Облако меток у меня есть только в музее юмора, а на ленте быть не должно. Значить достаточно разместить ссылку на некоторых страницах музея юмора (но не ленты экспонатов, чтобы не вводить в заблуждение посетителей). Я разместил на странице отображения всех экспонатов музея и на детальном просмотре. А теперь нажмем...
Метки кликабельны, а значит получилось то, что и требовалось.
Заключение
Вы можете скачать текущую версию проекта, если у вас что-то не получилось или что-то не понятно. А мне осталось сказать: "спасибо за внимание".
Подробнее: http://feedproxy.google.com/~r/blogmusor/~3/Zf3dmc9ghKs/86
Дайджест новых статей по интернет-маркетингу на ваш email
Новые статьи и публикации
- 2024-11-26 » Капитан грузового судна, или Как начать использовать Docker в своих проектах
- 2024-11-26 » Обеспечение безопасности ваших веб-приложений с помощью PHP OOP и PDO
- 2024-11-22 » Ошибки в Яндекс Вебмастере: как найти и исправить
- 2024-11-22 » Ошибки в Яндекс Вебмастере: как найти и исправить
- 2024-11-15 » Перенос сайта на WordPress с одного домена на другой
- 2024-11-08 » OSPanel 6: быстрый старт
- 2024-11-08 » Как установить PhpMyAdmin в Open Server Panel
- 2024-09-30 » Как быстро запустить Laravel на Windows
- 2024-09-25 » Next.js
- 2024-09-05 » OpenAI рассказал, как запретить ChatGPT использовать содержимое сайта для обучения
- 2024-08-28 » Чек-лист: как увеличить конверсию интернет-магазина на примере спортпита
- 2024-08-01 » WebSocket
- 2024-07-26 » Интеграция с Яндекс Еда
- 2024-07-26 » Интеграция с Эквайринг
- 2024-07-26 » Интеграция с СДЕК
- 2024-07-26 » Интеграция с Битрикс-24
- 2024-07-26 » Интеграция с Travelline
- 2024-07-26 » Интеграция с Iiko
- 2024-07-26 » Интеграция с Delivery Club
- 2024-07-26 » Интеграция с CRM
- 2024-07-26 » Интеграция с 1C-Бухгалтерия
- 2024-07-24 » Что такое сторителлинг: техники и примеры
- 2024-07-17 » Ошибка 404: что это такое и как ее использовать для бизнеса
- 2024-07-03 » Размещайте прайс-листы на FarPost.ru и продавайте товары быстро и выгодно
- 2024-07-01 » Профилирование кода в PHP
- 2024-06-28 » Изучаем ABC/XYZ-анализ: что это такое и какие решения с помощью него принимают
- 2024-06-17 » Зачем вам знать потребности клиента
- 2024-06-11 » Что нового в работе Яндекс Метрики: полный обзор обновления
- 2024-06-11 » Поведенческие факторы ранжирования в Яндексе
- 2024-06-11 » Скорость загрузки сайта: почему это важно и как влияет на ранжирование
Жизнь подобна универмагу: в ней находишь всё, кроме того, что ищешь Кроткий Эмиль - (1892—1963) - русский поэт–сатирик, юморист и афорист |
Мы создаем сайты, которые работают! Профессионально обслуживаем и продвигаем их , а также по всей России и ближнему зарубежью с 2006 года!
Как мы работаем
Заявка
Позвоните или оставьте заявку на сайте.
Консультация
Обсуждаем что именно Вам нужно и помогаем определить как это лучше сделать!
Договор
Заключаем договор на оказание услуг, в котором прописаны условия и обязанности обеих сторон.
Выполнение работ
Непосредственно оказание требующихся услуг и работ по вашему заданию.
Поддержка
Сдача выполненых работ, последующие корректировки и поддержка при необходимости.