Настройка 360-фото товаров на 1С-Битрикс
Покупатель хочет осмотреть товар со всех сторон до заказа. Обычная галерея из 8 фото не заменяет возможность повернуть объект. 360-просмотр — это последовательность кадров (24-72 снимка), которые при перетаскивании создают иллюзию вращения.
Хранение кадров 360-съёмки
360-кадры хранятся как обычные изображения, привязанные к товару через свойство инфоблока типа «Файл» (F) с флагом «Множественное». Свойство создаётся с кодом, например, IMAGES_360.
При добавлении кадров через административную часть они сохраняются в b_iblock_element_property с PROPERTY_TYPE = 'F' — каждый кадр отдельной строкой с общим IBLOCK_ELEMENT_ID и IBLOCK_PROPERTY_ID.
Получение кадров для фронтенда:
$element = \CIBlockElement::GetByID($productId)->GetNextElement();
$props = $element->GetProperties();
$frames = $props['IMAGES_360']['VALUE'];
// $frames — массив ID файлов из b_file
$frameUrls = array_map(function($fileId) {
return \CFile::GetPath($fileId);
}, (array)$frames);
// Передать в JSON для JS-плеера
echo json_encode(['frames' => $frameUrls]);
JavaScript-плеер для 360
Простейшая реализация без сторонних библиотек — на Canvas или CSS background-position. Библиотека three-sixty.js или js-cloudimage-360-view подходят для production.
Реализация на базе CSS-спрайта (когда все кадры склеены в один горизонтальный спрайт):
class Viewer360 {
constructor(el, frames) {
this.el = el;
this.frames = frames;
this.total = frames.length;
this.current = 0;
this.dragging = false;
this.startX = 0;
this.img = new Image();
this.img.src = frames[0];
el.appendChild(this.img);
el.addEventListener('mousedown', e => { this.dragging = true; this.startX = e.clientX; });
document.addEventListener('mouseup', () => { this.dragging = false; });
document.addEventListener('mousemove', e => this.onMove(e));
// Touch
el.addEventListener('touchstart', e => { this.dragging = true; this.startX = e.touches[0].clientX; });
document.addEventListener('touchend', () => { this.dragging = false; });
document.addEventListener('touchmove', e => this.onMove(e.touches[0]));
}
onMove(e) {
if (!this.dragging) return;
const delta = e.clientX - this.startX;
if (Math.abs(delta) > 5) {
this.current = (this.current + (delta > 0 ? 1 : -1) + this.total) % this.total;
this.img.src = this.frames[this.current];
this.startX = e.clientX;
}
}
}
Инициализация в шаблоне компонента bitrix:catalog.element:
new Viewer360(
document.getElementById('viewer-360'),
<?= json_encode($frameUrls) ?>
);
Предзагрузка кадров
При ленивой загрузке кадров вращение будет лагать при первом прокруте. Правильный подход — предзагрузить все кадры в фоне после загрузки страницы:
function preloadFrames(urls) {
return Promise.all(urls.map(url => {
return new Promise(resolve => {
const img = new Image();
img.onload = resolve;
img.src = url;
});
}));
}
preloadFrames(frameUrls).then(() => {
// Разблокировать управление после загрузки
document.getElementById('viewer-360').classList.remove('loading');
});
До завершения предзагрузки контейнер блокируется спиннером.
Оптимизация: WebP и размер кадров
36 кадров по 800×600px в JPEG 80% = ~3-5 МБ общего веса. Для мобильных сетей это много. Оптимизация:
- Конвертация в WebP через
cwebpили через компонент ресайза Битрикса с форматомwebp. - Уменьшение разрешения кадров до 600×450 — для 360-вращения этого достаточно.
- Прогрессивная загрузка: сначала показывать первый кадр, остальные — в фоне.
Битрикс генерирует WebP через \CFile::ResizeImageGet() с параметром 'format' => 'webp' начиная с определённых версий. Для старых версий — внешний конвертер через exec('cwebp ...') при загрузке изображений.
Хранение в отдельном инфоблоке
Для каталогов с сотнями товаров, имеющих 360-наборы, хранение кадров в свойстве основного инфоблока создаёт большое количество записей в b_iblock_element_property. Альтернатива — отдельный инфоблок для 360-галерей с привязкой к товару через PROPERTY_TYPE = 'E' (связь с элементом). Это упрощает управление наборами и позволяет привязывать один набор к нескольким SKU.







