Реализация WebXR (VR/AR в браузере) на сайте

Когда пользователь нажимает «Посмотреть в AR», но на его устройстве ничего не происходит, это теряет доверие к вашему продукту. Мы реализуем WebXR-проекты под ключ, создавая VR и AR-опыт прямо в браузере с учётом всех платформ. Наша команда обеспечивает корректную работу на каждом устройстве и последующую поддержку, чтобы ваш иммерсивный контент был доступен каждому клиенту.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Реализация WebXR (VR/AR в браузере) на сайте
Сложный
от 2 недель до 3 месяцев
Часто задаваемые вопросы

Пользователь открывает страницу на iPhone с Safari и видит кнопку «Посмотреть в AR» — но ничего не происходит. Модель не загружается, потому что WebXR AR не поддерживается на iOS. На Android Chrome та же модель работает идеально. Такая ситуация — типичная ошибка при внедрении иммерсивного опыта: без учёта платформенных различий половина аудитории остаётся за бортом. Мы реализуем WebXR-проекты под ключ: VR и AR опыт прямо в браузере, с корректным fallback для каждого устройства. За 5 лет мы сделали более 50 проектов в этой области, накопили библиотеку типовых решений и оптимизаций.

Типичные проблемы при внедрении WebXR

Первая ошибка — игнорирование различий платформ. Android Chrome поддерживает immersive-ar; iOS — только AR Quick Look через USDZ. Без fallback пользователи iPhone видят пустой экран. Вторая — производительность: тяжёлые модели с высокополигональной геометрией вызывают тормоза на мобильных, а неправильная настройка LOD увеличивает время загрузки в 2–3 раза. Третья — отсутствие hit-testing (размещение объектов на реальных поверхностях) ухудшает впечатление от AR. Экономия времени на этом этапе оборачивается потерей до 40% вовлечённости. Свяжитесь с нами для аудита вашей 3D-модели — мы подскажем, как оптимизировать её под мобильные устройства.

Как обеспечить поддержку на всех устройствах?

Мы используем комбинированный подход: определяем платформу через user-agent, для Android запускаем WebXR AR-сессию с hit-testing, для iOS показываем ссылку на USDZ через AR Quick Look. На десктопе и для VR-гарнитур — immersive-vr. Детекция реализуется в несколько строк, как показано ниже. Рекомендуется также проверять поддержку через navigator.xr.isSessionSupported перед показом интерфейса.

const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent)
const isAndroid = /Android/.test(navigator.userAgent)
if (isIOS) {
  document.getElementById('ar-link')!.style.display = 'block' // USDZ
} else if (isAndroid && await navigator.xr?.isSessionSupported('immersive-ar')) {
  document.getElementById('ar-button')!.style.display = 'block' // WebXR AR
}

Почему Three.js — лучший выбор для кастомизации WebXR?

Three.js даёт полный контроль над рендерингом, анимацией, контроллерами. Он быстрее A-Frame в 2–3 раза при сложной физике и большом количестве объектов. Реализация hit-testing, ригелей, реакции на контроллеры — на уровне API. A-Frame хорош для быстрых прототипов, но для продакшена с уникальным UX выбираем Three.js. Альтернатива — React Three Fiber, который предоставляет React-обёртку над Three.js и упрощает интеграцию в современные проекты.

Three.js + WebXR

Three.js имеет встроенную поддержку WebXR:

import * as THREE from 'three'
import { ARButton } from 'three/examples/jsm/webxr/ARButton'
import { VRButton } from 'three/examples/jsm/webxr/VRButton'
import { XRControllerModelFactory } from 'three/examples/jsm/webxr/XRControllerModelFactory'

function WebXRScene({ mode }: { mode: 'ar' | 'vr' }) {
  const mountRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    const container = mountRef.current!
    const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true })
    renderer.setPixelRatio(window.devicePixelRatio)
    renderer.setSize(container.clientWidth, container.clientHeight)
    renderer.xr.enabled = true
    container.appendChild(renderer.domElement)

    const scene = new THREE.Scene()
    const camera = new THREE.PerspectiveCamera(70, container.clientWidth / container.clientHeight, 0.01, 100)

    scene.add(new THREE.AmbientLight(0xffffff, 1))
    const dirLight = new THREE.DirectionalLight(0xffffff, 2)
    dirLight.position.set(0, 5, 3)
    scene.add(dirLight)

    const button = mode === 'ar'
      ? ARButton.createButton(renderer, {
          requiredFeatures: ['hit-test'],
          optionalFeatures: ['dom-overlay'],
          domOverlay: { root: container },
        })
      : VRButton.createButton(renderer)
    document.body.appendChild(button)

    if (mode === 'vr') {
      const controllerModelFactory = new XRControllerModelFactory()
      for (let i = 0; i < 2; i++) {
        const controller = renderer.xr.getController(i)
        controller.addEventListener('selectstart', onSelectStart)
        controller.addEventListener('selectend', onSelectEnd)
        scene.add(controller)

        const controllerGrip = renderer.xr.getControllerGrip(i)
        controllerGrip.add(controllerModelFactory.createControllerModel(controllerGrip))
        scene.add(controllerGrip)
      }
    }

    let hitTestSource: XRHitTestSource | null = null
    let hitTestSourceRequested = false
    const reticle = createReticle()
    scene.add(reticle)

    renderer.xr.addEventListener('sessionstart', async () => {
      if (mode !== 'ar') return
      const session = renderer.xr.getSession()!
      const viewerSpace = await session.requestReferenceSpace('viewer')
      hitTestSource = await session.requestHitTestSource!({ space: viewerSpace })!
    })

    renderer.setAnimationLoop((timestamp, frame) => {
      if (mode === 'ar' && frame) {
        const referenceSpace = renderer.xr.getReferenceSpace()!
        const hitTestResults = frame.getHitTestResults(hitTestSource!)
        if (hitTestResults.length > 0) {
          const hit = hitTestResults[0]
          const pose = hit.getPose(referenceSpace)
          if (pose) {
            reticle.visible = true
            reticle.matrix.fromArray(pose.transform.matrix)
          }
        } else {
          reticle.visible = false
        }
      }
      renderer.render(scene, camera)
    })

    function onSelectStart(event: THREE.Event) {
      if (reticle.visible) {
        const geometry = new THREE.BoxGeometry(0.1, 0.1, 0.1)
        const material = new THREE.MeshStandardMaterial({ color: 0x2563eb })
        const mesh = new THREE.Mesh(geometry, material)
        mesh.position.setFromMatrixPosition(reticle.matrix)
        mesh.quaternion.setFromRotationMatrix(reticle.matrix)
        scene.add(mesh)
      }
    }

    return () => {
      renderer.setAnimationLoop(null)
      renderer.dispose()
      button.remove()
      container.removeChild(renderer.domElement)
    }
  }, [mode])

  return (
    <div ref={mountRef} style={{ width: '100%', height: '600px', position: 'relative' }} />
  )
}

function createReticle(): THREE.Mesh {
  const geometry = new THREE.RingGeometry(0.05, 0.07, 32).rotateX(-Math.PI / 2)
  const material = new THREE.MeshBasicMaterial({ color: 0xffffff, side: THREE.DoubleSide })
  const reticle = new THREE.Mesh(geometry, material)
  reticle.matrixAutoUpdate = false
  reticle.visible = false
  return reticle
}

Сравнение подходов для AR в браузере

Параметр WebXR AR AR Quick Look A-Frame AR
Поддержка iOS Нет Да Нет
Интерактивность Высокая (hit-test, контроллеры) Низкая (только просмотр) Средняя (ограниченная)
Сложность интеграции Средняя Низкая (ссылка+USDZ) Низкая
Производительность Зависит от модели Нативная Хорошая
Кастомизация Полная Минимальная Средняя

Сравнение фреймворков: Three.js vs A-Frame

Критерий Three.js A-Frame
Производительность Высокая (до 60fps на мобильных) Средняя (до 30fps на сложных сценах)
Гибкость Полный контроль над рендерингом Ограничен декларативными компонентами
Кривая обучения Крутая (требует знания 3D-графики) Пологая (HTML-подобный синтаксис)
Поддержка WebXR Полная (контроллеры, hit-test) Базовая (контроллеры через компоненты)

iOS: AR Quick Look

Safari iOS не поддерживает WebXR AR, но поддерживает AR Quick Look через USDZ-файлы:

<a href="/models/product.usdz" rel="ar" id="ar-link">
  <img src="/models/product-preview.jpg" alt="Просмотр в AR" />
  <span>Посмотреть в вашем интерьере</span>
</a>

Конвертация 3D-моделей

Для AR Quick Look нужен USDZ, для WebXR — GLTF. Конвертацию выполняем через Blender или утилиты командной строки, например, usd-from-gltf. Потери качества при правильных настройках экспорта минимальны. Подробнее о форматах — в официальной документации WebXR.

Пример: оптимизация модели перед конвертацией Для мобильных устройств рекомендуется снижать количество полигонов до 50 000, использовать текстуры 1024x1024 и объединять материалы. Это уменьшает размер модели на 60% и ускоряет загрузку.

Что входит в работу

  • Анализ целевых устройств и платформ
  • Подготовка 3D-моделей (оптимизация под мобильные, конвертация в необходимые форматы)
  • Реализация WebXR AR/VR сцены с hit-testing и поддержкой контроллеров
  • Интеграция iOS AR Quick Look с корректным fallback
  • Тестирование на реальных устройствах (Android, iPhone, Quest)
  • Передача документации и исходных кодов
  • Обучение вашей команды работе с решением

Этапы разработки

  1. Аналитика — определяем сценарии использования, выбираем стек (Three.js, A-Frame, React Three Fiber).
  2. Проектирование — прототип взаимодействия, схема сцены, оценка бюджета.
  3. Реализация — код WebXR, интеграция с вашим сайтом, оптимизация производительности.
  4. Тестирование — проверка на гарнитурах и телефонах, исправление ошибок, замер Core Web Vitals.
  5. Деплой — настройка HTTPS, публикация моделей, CDN для быстрой загрузки.

Сроки ориентировочно

  • AR-просмотр продукта (Android + iOS) — 5–7 дней.
  • Интерактивная VR-сцена с контроллерами — 8–12 дней.
  • Полный цикл с кастомизацией — от 14 дней.

Стоимость рассчитывается индивидуально. Наши инженеры имеют 10+ лет опыта в 3D-графике и веб-разработке. Получите консультацию по вашему проекту — мы оценим сложность и предложим оптимальное решение.

Наши компетенции:

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1393
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1368
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1139
  • Разработка веб-сайта для компании ФИКСПЕР
    Разработка веб-сайта для компании ФИКСПЕР
    1060