Начните свой веб-сайт теории графов с помощью WebSharper
Теория графов прекрасна. Я всегда любил графики и наборы, но никогда бы не подумал, что из них получится хороший сайт. Cytoscape.js и WebSharper доказали, что я ошибался!
В предыдущем своем рассказе я рассказывал об этом и его привязке к WebSharper, вы можете прочитать это здесь:
Эта история — лишь основа этого замечательного расширения. Сегодня мы создадим более сложный, но еще более красивый маленький веб-сайт с графикой.
Графики об отношениях людей всегда интересны. Давайте посмотрим что-то вроде числа Эрдёша, реализованное в виде графика. Какой в этом смысл? У нас могут быть люди как узлы и ребра как отношения. Если мы свяжем каждого человека с другим каким-то правилом, мы получим красивый граф. На этом графе мы можем делать алгоритмы графа, например: Звезда, чтобы найти кратчайший путь между двумя людьми.
Просто для простоты я буду использовать случайные имена и случайные отношения в нашем небольшом примере, но вы можете (это забавный проект) реализовать в этом примере всю задачу о числах Эрдёша.
Настройка проекта
Все, что нам нужно, это одностраничное приложение WebSharper для этого небольшого проекта. Создайте его и получите Zafir.Cytoscape
(или WebSharper.Cytoscape
) от NuGet!
Индекс.html
Если вы читали мои истории (если нет, то эта — идеальное начало), как обычно, начнем с html-файла. Нам действительно не нужно много всего, просто один div
с и id
и тег stlye с высотой. Назовем наш div
main:
<div id="main" style="height:90vh;"></div>
На этом мы закончили с html файлом. Давайте перейдем к нашему Client.fs
!
Клиент.fs
Прежде чем кодировать, давайте подумаем. Что нам нужно?
- Список людей
- Список отношений людей
- Настройка графика
- Функция для нашего алгоритма A Star
Список людей
Список людей легко. Как я уже сказал, я буду использовать случайные имена, но вы можете использовать любой список имен:
Вы можете использовать любое представление, какое захотите, но я использую списки. Это всего лишь личное предпочтение.
Список отношений людей
У нас есть много способов сделать это. Я подумал, что мы могли бы использовать список с парами:
Человек, Список людей
Во втором списке мы могли бы иметь людей, с которыми наш человек имеет какие-то отношения.
Давайте посмотрим код для него:
Настройка графика
Прежде чем мы сможем это сделать, нам нужен список узлов и ребер из наших списков.
Узлы
Создавать узлы легко, мы можем просто сопоставить конструктор узлов с нашим списком people
следующим образом:
Каждый узел будет иметь имя человека в виде id
. Нам это понадобится во время A Star.
Границы
Может показаться, что это немного сложнее, но это не так! Все, что нам нужно сделать, это дважды отобразить наш конструктор! Давайте посмотрим код для него:
Сначала мы получаем наши пары, затем мы сопоставляем конструктор ребер с нашим списком отношений. Это приведет к списку в списке, но мы можем решить это с помощью простого List.Concat
. Наши ребра имеют три свойства:
- id: конкатенация имен двух людей (это всегда будет уникальным, так как у нас нет параллельных ребер)
- источник: человек
- Цель: люди из списка в паре с человеком
Элементы
Осталось только одно: создать единый массив списков узлов и ребер. Для этого у нас есть функция List.Append
. Но нашему графику понадобится массив, поэтому нам также придется вызвать List.toArray
:
График
Как мы видели в основах, нам понадобятся четыре вещи:
- Контейнер для нашего графа
- Набор элементов
- Стиль графика
- Макет
Контейнер прост, мы просто получаем элемент DOM для нашего созданного «основного» div
с JS.Document.GetElementById "main"
.
Элементы, которые мы только что закончили.
Для стиля я собираюсь использовать те же настройки, что и для нашего базового примера, с одним отличием: теперь нам нужен селектор :selected
, чтобы сделать видимым наш путь A Star.
В моем примере макет circle
работал лучше всего, но поэкспериментируйте с макетами, чтобы найти тот, который вам нравится!
Давайте посмотрим полный код нашего графа:
Функция для нашего алгоритма A Star
У нас есть много способов сделать это. Я обнаружил, что лучший способ сделать это — щелкнуть правой кнопкой мыши на узлах, которые мы хотим соединить.
К счастью, в Cytoscape уже реализован алгоритм A Start, поэтому все, что нам нужно сделать, это написать обработчик события правого клика. Для этого нам нужно создать несколько реактивных переменных с Var.Create
. Мы собираемся использовать два для идентификатора узлов и один, чтобы узнать, находимся ли мы на первом или втором узле, который хотим выбрать.
Давайте поработаем над нашим обработчиком событий. У этой функции есть параметр Dom.Event
, и мы будем использовать его Target
, а это свойство id
. Что должна делать эта функция? Проверьте, находимся ли мы на первом или втором узле, сохраните идентификатор узла, и если мы находимся на втором узле, выполните алгоритм A Star и выберите путь. (Конечно, нам придется отменить выбор предыдущего пути.) Вот код:
В нашем AlgorithmOptions
для Root
и Goal
мы должны использовать Union2Of2, так как мы даем функции строку селектора, а не объект Node.
В конце все, что нам нужно сделать, это привязать нашу функцию changeAStar
к событию ctxtap
для каждого node
. ( ctxtap
— это событие щелчка правой кнопкой мыши и касания двумя пальцами.)
Я также заблокировал узлы, чтобы случайно не перемещать узлы при выборе, но вы можете удалить это, может быть забавно поиграть с этим.
Результат
На этом мы закончили наш график, код готов к запуску!
Если вы хотите поиграть с кодом, вы можете сделать это в своем браузере! Попробуйте код, который мы написали в Try WbSharper, по этой ссылке:
Обязательно оставьте 💚, это поможет мне узнать, какие истории вы хотите прочитать, и оставьте комментарий, если у вас есть какие-либо вопросы! Надеюсь, вам было интересно читать этот пост, и вы полюбили F# и WebSharper.