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

- Перетащите файл
.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/> с загрузкой по требованию:

'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.