Виртуальный тур обещает зрителю прогулку по отелю, музею или квартире без визита на объект, и на этом обещании строится целая индустрия продаж недвижимости, экспозиций и производственных площадок. Обещание быстро разбивается о практику: зритель открывает первую панораму, крутит её несколько секунд, не понимает, куда идти дальше, и закрывает вкладку. Провал почти всегда связан не с качеством съёмки, а с навигацией. Ниже разобрано, как устроен тур на техническом уровне, чем отличаются управление мышью и гироскопом, как проектировать переходы между сценами и планы этажей, а также какие метрики показывают, что тур действительно ведёт зрителя по маршруту, а не сбрасывает его на полпути.

Как устроен виртуальный тур в браузере и из чего состоит панорамная сцена

Основой тура служит равнопромежуточная панорама: плоское изображение с соотношением сторон строго два к одному, например 6000 на 3000 или 8192 на 4096 пикселей. Такая картинка натягивается на внутреннюю поверхность сферы, а камера ставится в центр. Зритель не двигается по фотографии, он лишь поворачивает виртуальную голову, меняя углы рысканья и тангажа. Классическая схема на three.js занимает несколько строк:

const geometry = new THREE.SphereGeometry(500, 64, 64);
const material = new THREE.MeshBasicMaterial({
  map: texture,
  side: THREE.BackSide
});
const sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
camera.position.set(0, 0, 0.1);

Материал с параметром THREE.BackSide рисует сферу изнутри, и панорама обретает глубину. Для быстрого старта годится декларативный подход A-Frame:

<a-scene>
  <a-sky src="/pano/kitchen.jpg"></a-sky>
  <a-entity cursor="rayOrigin: mouse"></a-entity>
</a-scene>

На рынке есть и готовые плееры: krpano описывает сцены и хотспоты в XML с координатами ath и atv, Marzipano даёт открытую библиотеку для 360-медиа, Pannellum остаётся лёгким открытым просмотрщиком на WebGL. Выбор движка влияет меньше, чем кажется: почти все плееры крутят одну и ту же сферу, и отличает туры именно слой навигации поверх неё.

Поле зрения камеры задают в диапазоне от 30 до 100 градусов: узкий угол приближает детали и укачивает меньше, широкий охватывает всё помещение, но растягивает картинку по краям. Рабочим компромиссом для помещений считается 70-90 градусов.

Управление мышью и гироскопом с запросом разрешений на iOS

На настольных компьютерах стандартом стало перетаскивание: зритель тянет картину мышью, инерция доводит её до остановки, колесо меняет приближение. Жест понятен без подсказок, однако его стоит дополнить стрелками клавиатуры, чтобы путь по панораме был доступен и без мыши.

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

async function enableGyro() {
  if (typeof DeviceOrientationEvent.requestPermission === 'function') {
    const state = await DeviceOrientationEvent.requestPermission();
    if (state === 'granted') {
      startGyroMode();
    }
  } else {
    startGyroMode();
  }
}

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

Автовращение оживляет панораму до первого касания: медленное вращение со скоростью около одного градуса в секунду намекает, что сцена интерактивная. После первого взаимодействия вращение обязано остановиться, иначе тур вступает в борьбу со зрителем и проигрывает её.

Хотспоты и переходы между сценами без потери ориентации

Хотспот это невидимая точка на сфере, помеченная значком, стрелкой или дверью. Точнее было бы назвать её узлом маршрута: один хотспот переносит в соседнюю сцену, второй открывает подпись с описанием, третий запускает аудио или видео. Смешивать типы в одном значке не стоит, зритель не должен угадывать последствия нажатия.

Правила размещения проверены практикой. Точки перехода ставят на уровне глаз, около 150-170 сантиметров от пола, в тех местах, куда человек пошёл бы в реальности: дверь, лестница, широкий проход. Зона нажатия для пальца держится размером не меньше 44 на 44 пикселя, при этом видимая иконка может быть меньше. Подпись с подсказкой появляется по наведению и держится на экране от 300 миллисекунд. В кадре единовременно видно от трёх до семи активных точек, остальное скрывают за поворотом камеры или сворачивают в меню сцен.

Внутри сферы хотспоты держат на маленьких плоскостях-невидимках, а попадание курсора проверяют лучом из камеры. Схема на three.js знакома каждому, кто работал с трёхмерными сценами:

const raycaster = new THREE.Raycaster();
const pointer = new THREE.Vector2();

function onPointerMove(event: PointerEvent) {
  pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
  pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
  raycaster.setFromCamera(pointer, camera);
  const hits = raycaster.intersectObjects(hotspotMeshes);
  showTooltip(hits.length > 0 ? hits[0].object.userData.label : null);
}

Луч из камеры через позицию курсора пересекает список плоскостей, и ближайшее пересечение даёт активный хотспот. В userData удобно держать подпись, тип действия и звук подтверждения: короткий тихий щелчок на переходе сообщает пальцу, что нажатие сработало, при том что общий звук в туре остаётся выключенным до явного согласия.

Начальный взгляд сцены заслуживает отдельного решения: камера при загрузке обязана смотреть на главный крючок помещения, будь то панорамное окно, лестница или предмет, ради которого зритель пришёл. Угол рысканья задаётся в конфигурации сцены, наклон камеры чуть ниже горизонта добавляет ощущение пространства. Взгляд в глухую стену при старте обесценивает даже безупречную панораму.

Переход между сценами скрывает техническую перезагрузку и создаёт ощущение шага вперёд. Рабочие варианты: плавное затемнение и появление новой панорамы за 200-400 миллисекунд, короткий зум в точку перехода или совместное исчезновение с лёгким смещением вперёд. Резкая подмена сцены без перехода сбивает зрителя, а слишком долгая анимация делает прогулку утомительной.

Критично правило непрерывности направления: после перехода камера должна смотреть туда же, куда смотрел зритель в предыдущей сцене. Если тур разворачивает вид на 180 градусов после каждого клика, маршрут превращается в лабиринт из дискомфорта.

Комфорт движения и предотвращение укачивания в панорамных турах

Укачивание в турах вызывает конфликт ощущений: глаза видят движение, вестибулярный аппарат его не подтверждает. Чем меньше рассинхрон, тем дольше зритель остаётся в туре. В режимах для шлемов ориентиром служит задержка от движения головы до смены картинки, инженерный ориентир здесь порядка 20 миллисекунд, а частота кадров шлемов держится на отметках 72 и 90 герц. На телефонах без шлема хватает честных 60 кадров в секунду, лаг ниже этого порода зритель считывает как сломанный тур.

Проход в виртуальный шлем открывает WebXR, стандарт, который заменил черновик WebVR и охватывает устройства с тремя или шестью степенями свободы. Проверка поддержки занимает одну строку:

const supported = await navigator.xr.isSessionSupported('immersive-vr');

При недоступности режима погружения тур честно предлагает сплит-просмотр для простых шлемов-картонных конструкций или остаётся в плоском режиме. Скрывать отсутствие режима нет смысла: попытка эмулировать погружение обернётся тошнотой и закрытой вкладкой.

Если в туре предусмотрено перемещение внутри сцены, работают приёмы из больших виртуальных миров: телепорт с коротким затемнением вместо непрерывного скольжения, поворот фиксированными шагами по 30 градусов, сужение поля зрения на время разгона и остановки. Лёгкая виньетка по краям экрана снимает нагрузку с периферийного зрения, где конфликт ощущений ощущается сильнее всего.

Ориентирование в туре через планы этажей и сцены-указатели

Панорамная сцена погружает, но не отвечает на вопрос, где зритель находится и что пропустил. Ответ дают внешние по отношению к сфере слои. План этажа с точками панорам показывает маршрут целиком, подсвечивает текущую позицию и направление взгляда стрелкой. Галерея миниатюр даёт быстрый переход к конкретному помещению без блужданий по маршруту. Ветки-подписи с названиями сцен работают как оглавление.

Согласованность направлений удобно держать в одном манифесте тура, где сцены, стартовый вид и хотспоты описаны данными, а не кодом:

{
  "start": "hall",
  "autoRotate": 1.0,
  "scenes": [
    {
      "id": "hall",
      "name": "Холл",
      "image": "/pano/hall.jpg",
      "initial": {"yaw": 0, "pitch": 0, "fov": 75},
      "hotspots": [
        {"type": "scene", "to": "kitchen", "yaw": 42, "pitch": -5},
        {"type": "info", "label": "Панорамные окна", "yaw": 10, "pitch": 8}
      ]
    }
  ]
}

Из манифеста следует полезное правило обратного перехода: если дверь в кухню стоит под углом 42 градуса, то хотспот возврата в холл внутри кухни ставится примерно под 222 градусами, то есть повёрнутым на 180 градусов. Зритель, шагнув назад, смотрит туда, откуда пришёл, и маршрут ощущается честным. Ссылки между сценами образуют граф, и проверка связности перед публикацией гарантирует, что ни одна панорама не останется островом.

Сильный ход для публичных пространств и музеев это режим экскурсии: тур сам ведёт по сценам, зритель лишь наблюдает и в любой момент перехватывает управление. Продолжительность прохода стоит держать в пределах трёх-пяти минут, для недвижимости это осмотр из шести-десяти панорам.

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

Собранные требования удобно свести в рабочий чек-лист перед публикацией:

  1. Первая сцена объясняет управление за пять секунд и показывает путь к следующей точке;
  2. Точки перехода стоят на уровне глаз в местах естественных проходов и снабжены подписями;
  3. Зона нажатия хотспота держит размер не меньше 44 на 44 пикселя на любом устройстве;
  4. Переход длится 200-400 миллисекунд и сохраняет направление взгляда зрителя;
  5. План, галерея сцен и режим экскурсии доступны с любой панели с одним касанием;
  6. Гироскоп, звук и режим погружения включаются только по явному согласию зрителя.

Скорость загрузки и доступность мобильных версий тура

Панорама в 8192 на 4096 пикселей весит мегабайты, и мобильный зритель платит за них временем. Рабочая схема двухступенчатая: сначала грузится лёгкая версия 2048 на 1024 пикселя размером до 400 килобайт, затем подкачивается полный кадр, а соседние сцены предзагружаются в фоне по ходу маршрута. Форматы WebP и AVIF срезают половину веса против классического JPEG при том же качестве. Крупные панорамы нарезают пирамидой тайлов: плеер запрашивает только видимые фрагменты на текущем приближении.

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

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

Метрики замыкают работу над навигацией. Доля зрителей, дошедших до финальной сцены, среднее время в панораме, отток на первой сцене, доля нажатий на точки перехода и повторные визиты показывают, где маршрут теряет людей. Турам, как и любым маршрутам, нужна разметка, а не только красивый вид из окна.

Навигация решает судьбу виртуального тура сильнее, чем разрешение панорам и цена плеера. Зритель приходит за погружением, а остаётся там, где понимает, где он, куда идёт и как вернуться. Хотспоты на уровне глаз, планы этажей, спокойные переходы и быстрая первая сцена складываются в прогулку, которую досматривают до конца, и именно это отличает рабочие туры от дорогостоящих загрузочных экранов.