Market --- 3D-просмотр товара (модели GLB)

Обновлено: Nov 3, 2026Раздел: Интеграции

К товару интеграции Market можно прикрепить необязательную 3D-модель. Витрина получает её публичный URL из внешнего API каталога и показывает интерактивный просмотр: покупатель вращает модель мышью или пальцем, приближает колесом или жестом. Если модели нет (или в браузере нет WebGL), витрина показывает обычное изображение товара.

Доступно начиная с Mailoo 1.34.13.

Загрузка модели в панели управления

  1. Откройте Панель → Проекты → ваш проект → интеграция Market → Товары и перейдите к редактированию товара.
  2. На вкладке Общее найдите блок 3D-модель.

Редактор товара Market с блоком «3D-модель»

  1. Перетащите файл .glb в зону загрузки (или нажмите на неё и выберите файл). Во время загрузки отображается индикатор прогресса.

Пустая зона загрузки 3D-модели

  1. Нажмите Опубликовать (или Сохранить как черновик), чтобы сохранить модель в товаре.

Блок «3D-модель» с загруженным файлом mouse.glb

После загрузки в блоке видны имя файла и id медиа, ссылка Открыть (публичный URL модели) и кнопка Удалить. Повторная загрузка заменяет модель; Удалить отвязывает её от товара при следующем сохранении.

Требования к файлу

  • Формат: только .glb --- бинарный glTF 2.0. Проверяется содержимое файла (заголовок glTF, версия 2): переименованный в .glb файл другого формата будет отклонён. .gltf с внешними текстурами, .obj, .fbx, .usdz для загрузки не принимаются --- сначала сконвертируйте их в GLB (например, Blender → Export glTF 2.0, формат glTF Binary).
  • Размер: до 50 МБ на файл (лимит отдельный от изображений). Для мобильных покупателей лучше держать модель в пределах нескольких МБ со сжатыми текстурами.
  • Изоляция: модель принадлежит той интеграции Market, в которую она загружена, и может быть прикреплена только к товарам этого же проекта и интеграции.

Внешняя ссылка (устаревшее)

Пока модель не загружена, в блоке доступно поле Или внешняя ссылка на модель (устаревшее) --- публичная https-ссылка на .glb / .gltf на стороннем хостинге. Поле устарело, предпочтительна загрузка файла. Загруженная модель всегда имеет приоритет над внешней ссылкой.

Что получает витрина

Товары во внешнем API каталога (см. market-catalog-external-api{.interpreted-text role="doc"}) содержат два поля:

  • model3dUrl --- итоговый URL модели для отображения или null. Для загруженной модели это публичный URL Mailoo {baseUrl}/api/v1/public/models/{mediaId}, иначе --- устаревшая внешняя ссылка.
  • model3dMediaId --- id загруженного GLB или null.
{
  "id": "mailoo_dev_market_demo_product",
  "attributes": { "name": "Mailoo Demo Widget" },
  "model3dUrl": "https://api.mailoo.app/api/v1/public/models/yblrqe9jgdkv1a3g5913cptv",
  "model3dMediaId": "yblrqe9jgdkv1a3g5913cptv"
}

Публичный эндпоинт модели не требует API-ключа, поэтому браузер загружает её напрямую. Ответ --- поток model/gltf-binary с CORS *, Cross-Origin-Resource-Policy: cross-origin и неизменяемым кэшем на год (при замене модели меняется и URL).

Отображение 3D-просмотра на сайте

Подойдёт любой просмотрщик glTF. Эталонная реализация в демо интегратора использует Google <model-viewer> <https://modelviewer.dev/> с загрузкой по требованию:

Интерактивный 3D-просмотр товара в демо-витрине интегратора

'use client'
import { createElement, useEffect, useState } from 'react'

const MODEL_VIEWER_SRC =
  'https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js'

export function Product3DViewer({ modelUrl, fallbackImageUrl, alt }: {
  modelUrl?: string | null
  fallbackImageUrl?: string | null
  alt: string
}) {
  const [ready, setReady] = useState(false)
  useEffect(() => {
    if (!modelUrl || customElements.get('model-viewer')) return setReady(!!modelUrl)
    const s = document.createElement('script')
    s.type = 'module'
    s.src = MODEL_VIEWER_SRC
    s.onload = () => setReady(true)
    document.head.appendChild(s)
  }, [modelUrl])

  if (!modelUrl || !ready) {
    return fallbackImageUrl ? <img src={fallbackImageUrl} alt={alt} /> : null
  }
  return createElement('model-viewer', {
    src: modelUrl,
    alt,
    poster: fallbackImageUrl ?? undefined,
    'camera-controls': '',   // drag to rotate, scroll/pinch to zoom
    'auto-rotate': '',
    'touch-action': 'pan-y', // keep vertical page scroll on mobile
    loading: 'lazy',
    'shadow-intensity': '1',
    style: { width: '100%', aspectRatio: '1 / 1' },
  })
}

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

<Product3DViewer
  modelUrl={product.model3dUrl}
  fallbackImageUrl={product.previewImageUrl}
  alt={product.attributes.name}
/>

Полная версия компонента в демо (tests/integrator-demo/src/components/product-3d-viewer.tsx) дополнительно:

  • Ленивая загрузка --- библиотека (~1 МБ) скачивается только когда просмотрщик попадает в область видимости (IntersectionObserver); страницы без 3D ничего не теряют в скорости.
  • Запасной вариант --- 2D-изображение, если model3dUrl пуст, WebGL недоступен или модель не загрузилась (событие error).

Решение проблем

  • «Only .glb (binary glTF 2.0) files are supported» / «File is not a valid GLB» --- экспортируйте модель как glTF Binary (.glb), glTF 2.0.
  • «Model too large» --- файл больше 50 МБ; уменьшите число полигонов или сожмите текстуры (например, gltf-transform optimize).
  • На витрине только картинка --- проверьте, что товар опубликован, что model3dUrl в ответе API не null и что браузер поддерживает WebGL.
📚