.

Захотелось показать возможности trip2g не абстрактно, а через живой пример. Решили сделать интерактивную фэнтези-карту с навигацией между локациями.

Что получилось

Три локации — лес, замок, подземелье гномов. Между ними переходы. На каждой странице:

  • Фоновая картинка на весь экран
  • Атмосферная музыка с плавным fade-in
  • Текст с выбором куда идти дальше
  • Миникарта в углу

Всё работает на обычных markdown-заметках с wikilinks.

Генерация картинок

Использовали FLUX.2 через fal.ai. Ключевое в промптах — просить "dark void in center for text overlay". Иначе картинка будет слишком детальной в центре и текст не читается.

7 картинок сгенерировали параллельно за пару минут:

  • start, forest, castle, dungeon
  • forest-to-castle, castle-to-dungeon, dungeon-to-forest

Шаблоны

Один блок map_layout в _blocks.html — туда приходит всё из frontmatter заметки:

  • bg_image — фон
  • env_track — музыка
  • theme — для декораций (пока отключены)

Каждая локация — отдельный layout-файл из 5 строк, который просто импортирует блок и объявляет зависимости для asset-трекинга.

Музыка

Три трека — лес, замок, горы. Автоплей с fade-in 2 секунды. Браузеры блокируют автоплей, поэтому вешаем обработчики на click/touch/scroll — при первом взаимодействии музыка включается.

Состояние сохраняется в localStorage. Кнопка в углу для вкл/выкл.

Грабли

asset() не работает с переменными в параметрах блока. Передавали bg_url=asset("map/forest.webp") — получали пустую строку. Решение — читать путь из frontmatter через note.M().GetString() и вызывать asset() внутри блока.

CSS url() не трекается движком. Фоны в CSS-классах давали 404. Решение — inline style с asset().

Относительные slug дублируются. slug: map/castle в папке map/ давал /map/map/castle. Решение — абсолютные пути /map/castle.

Динамические asset() не видны парсеру. asset("map/" + variable) не создаёт зависимость. Решение — статические объявления в комментариях layout-файлов.

Версия 2: кинематограф

Первая версия работала, но переходы были резкими — клик, перезагрузка страницы, музыка начинается заново. Решили сделать по-настоящему атмосферно.

SPA-навигация без фреймворка

Вместо перезагрузки страницы — fetch + DOMParser:

  1. Перехватываем клик по ссылке
  2. Загружаем HTML целевой страницы через fetch
  3. Парсим через new DOMParser().parseFromString(html, 'text/html')
  4. Вытаскиваем нужные элементы: заголовок, контент, стили фона
  5. Обновляем DOM с плавной анимацией
  6. Меняем URL через history.pushState

Музыка не прерывается. При смене трека — crossfade.

Эффект камеры

Добавили параметры в frontmatter:

cam_scale: "1.15"
cam_origin: "50% 25%"

CSS делает остальное:

.map-bg {
  transform: scale(var(--cam-scale, 1));
  transform-origin: var(--cam-origin, 50% 50%);
  transition: transform 0.8s ease-out;
}

При переходе между шагами фон плавно зумится к точке назначения. Идёшь к замку — камера медленно приближается к нему на горизонте.

Длинные маршруты

Вместо телепортов между локациями — коридоры из 3 шагов. Одна картинка, но разный zoom:

  • Шаг 1: scale: 1.0 — видишь цель вдали
  • Шаг 2: scale: 1.15 — приближаешься
  • Шаг 3: scale: 1.3 — почти пришёл

Создаёт ощущение пути и дистанции.

Дыхание сцены

Фон едва заметно покачивается — 8 пикселей за 12 секунд:

.map-bg {
  inset: -20px; /* чтобы края не вылезали */
  animation: bg-sway 12s ease-in-out infinite;
}

@keyframes bg-sway {
  0%, 100% { translate: 0 0; }
  25% { translate: 8px 4px; }
  50% { translate: -4px 8px; }
  75% { translate: -8px -4px; }
}

Незаметно, но добавляет жизни. Как будто смотришь через слегка колышущееся стекло.

Типографика

Для заголовков поставили Cormorant SC — шрифт с капителями и характером старинных карт. Google Fonts, поддерживает кириллицу. Золотой цвет #fcd34d и градиентная рамка добавляют эпичности.

Версия 3: ветвление сюжета

Линейная навигация — это хорошо, но скучно. Добавили первую развилку с последствиями.

Встреча с гоблином

В подземелье из бокового туннеля выскакивает гоблин. Два варианта:

Драться — гоблин отступает в свою пещеру. Но войти туда нельзя: такая вонь, что глаза слезятся. Проход закрыт.

Бежать — герой проскакивает мимо, спотыкается о камень, кувыркается. Встаёт — гоблина нет. Повезло.

Оба исхода ведут дальше, но с разным текстом и ощущением. Это не влияет на прохождение, но создаёт иллюзию выбора и последствий.

Три уникальных фона

Для каждой сцены — своя картинка:

  • Встреча: гоблин с ножом выскакивает из-за кристаллов
  • После драки: вход в логово с токсичным зелёным туманом и костями
  • После побега: POV с пола, гоблин убегает вдаль

Генерировали через FLUX.2 с теми же принципами: тёмный центр для текста, зелёные кристаллы для визуальной связи с основной локацией подземелья.

Масштабирование

Добавить новую развилку — это:

  1. Создать 2-3 markdown-файла с frontmatter
  2. Сгенерировать фоны (опционально)
  3. Добавить asset-объявления в layout

Никакого кода. Сценарист может работать в Obsidian, не трогая шаблоны.

Итого

Из простой демки получился мини-квест с атмосферой:

  • SPA-навигация — музыка не прерывается, переходы плавные
  • Эффект камеры — фон зумится к цели при движении
  • Дыхание сцены — еле заметное покачивание фона
  • Ветвление сюжета — выборы с последствиями и уникальными фонами
  • Типографика — шрифт как на старых картах

Всё это — markdown + frontmatter + ~180 строк JS в одном шаблоне. Контент отделён от кода. Сценарист пишет в Obsidian, не трогая HTML.

Никаких React, Vue, билдеров. Просто HTML, CSS и vanilla JS.

Кому это нужно

Образование

Учителя истории — интерактивные карты событий. Ученик стоит на развилке: Наполеон идёт на Москву или отступает? Каждый выбор — своя ветка с последствиями. История перестаёт быть списком дат.

Преподаватели языков — квесты для изучения лексики. Ты в таверне, нужно заказать еду. Не знаешь слово — выбираешь наугад — получаешь не то блюдо. Запоминается лучше, чем карточки.

Онлайн-школы — геймификация курсов. Вместо "Урок 1, Урок 2" — путешествие по карте знаний. Прошёл тему — открылась новая локация.

Игры и нарратив

DND-мастера — квесты прямо в Obsidian, где они и так ведут кампании. Игроки открывают ссылку и видят локацию с картинкой и музыкой. Мастер не описывает словами — показывает.

Инди-разработчики — прототипы без движка. Проверить сюжет до того, как писать код. Собрал за вечер, дал потестить, понял что работает.

Писатели — интерактивная проза. Читатель сам выбирает, за кем следить. Несколько финалов. Книга, которую перечитывают.

Бизнес

Презентации продуктов — клиент сам выбирает что смотреть. Интересуют цены? Сюда. Техничка? Туда. Кейсы? Вот. Не листать 40 слайдов, а идти по своему пути.

Онбординг сотрудников — новичок проходит квест по компании. Познакомился с отделом — получил артефакт. Веселее, чем PDF на 50 страниц.

Выбор тарифа — вместо таблицы сравнения три двери. За каждой — своя история. "Ты стартап? Тебе сюда. Корпорация? Тебе туда."

Творческие проекты

Детские интерактивные сказки — ребёнок выбирает, куда идёт колобок. Съели или убежал — зависит от решений. Родители читают вместе, каждый раз новый финал.

Виртуальные экскурсии — музей без очередей. Хочешь — иди в зал импрессионистов. Хочешь — в древний Египет. С музыкой эпохи и фотографиями в полный экран.

Онлайн escape-room'ы — загадки на страницах, правильный ответ открывает следующую комнату. Можно продавать как продукт или использовать для тимбилдинга.

Что дальше

Шаблоны для презентаций

Планируем сделать отдельные шаблоны под презентации. Идея простая: накидал несколько заметок, связал ссылками — презентация готова.

Фишка в том, что можно собирать разные презентации из одних и тех же заметок. Под одного клиента — одна подборка. Под другого — другая. Со временем накапливается база, из которой собирается любая презентация под любой разговор. Не слайды листать, а вести собеседника по графу знаний.

Закрытый контент

Некоторые страницы можно закрыть — не обязательно за деньги.

Платный доступ — в игре есть торговец. У него можно купить карту сокровищ. За реальные деньги. После оплаты открывается страница с секретным лором или бонусной веткой сюжета.

По коду — организатор квеста раздаёт коды участникам. Ввёл код — открылась локация. Можно для тимбилдинга, можно для закрытых мероприятий.

По email — DND-мастер открывает карту только своим игрокам. Или учитель — только своему классу. Никаких регистраций на сторонних сервисах.

Технически это уже работает в trip2g. Осталось красиво обернуть в игровую механику.


Попробовать: /map

Готовы попробовать?

Напишите в Telegram — поможем настроить и покажем примеры.

Написать в Telegram