Налаштування zoom-просмотру зображень товарів у 1С-Бітрікс
Покупатель хочет розглянути серійний номер на етикетці або текстуру тканини. Стандартний компонент карточки товара Бітрікса показує зображення фіксованого розміру. Зум додається на рівні шаблону компонента без змін ядра.
Зображення товара в каталозі
Основне зображення товара зберігається у властивості інфоблока типу F з кодом MORE_PHOTO (множественное) або у полях PREVIEW_PICTURE / DETAIL_PICTURE таблиці b_iblock_element — ID файлів з b_file.
Для зуму потрібна оригінальна версія зображення в високій роздільній здатності. Проблема: стандартний ресайз Бітрікса зменшує зображення при збереженні через \CFile::ResizeImageGet(). Оригінал залишається в b_file з повним шляхом.
Отримання шляху до оригіналу та ресайзу:
$detailPictureId = $arResult['DETAIL_PICTURE']['ID'];
// Оригінал (для зуму)
$originalPath = \CFile::GetPath($detailPictureId);
// Превью для відображення (400x400)
$previewInfo = \CFile::ResizeImageGet($detailPictureId, ['width' => 400, 'height' => 400], BX_RESIZE_IMAGE_PROPORTIONAL, true);
$previewPath = $previewInfo['src'];
Зум через CSS transform
Найпростіший зум без бібліотек — CSS cursor: zoom-in + transform: scale при клику. Підходить для базових потреб:
.product-image-zoom {
overflow: hidden;
cursor: zoom-in;
position: relative;
}
.product-image-zoom img {
transition: transform 0.3s ease;
transform-origin: var(--zoom-x, 50%) var(--zoom-y, 50%);
}
.product-image-zoom.zoomed img {
transform: scale(2.5);
cursor: zoom-out;
}
const container = document.querySelector('.product-image-zoom');
const img = container.querySelector('img');
container.addEventListener('mousemove', function (e) {
if (!container.classList.contains('zoomed')) return;
const rect = container.getBoundingClientRect();
const x = ((e.clientX - rect.left) / rect.width * 100).toFixed(1) + '%';
const y = ((e.clientY - rect.top) / rect.height * 100).toFixed(1) + '%';
container.style.setProperty('--zoom-x', x);
container.style.setProperty('--zoom-y', y);
});
container.addEventListener('click', function () {
container.classList.toggle('zoomed');
if (container.classList.contains('zoomed')) {
img.src = img.dataset.originalSrc;
}
});
У шаблоні компонента:
<div class="product-image-zoom">
<img src="<?= $previewPath ?>"
data-original-src="<?= $originalPath ?>"
alt="<?= htmlspecialchars($arResult['NAME']) ?>">
</div>
Lens-зум (ефект лупи)
Більш професійне рішення — «лінза»: при наведенні на мініатюру рядом з'являється збільшена область. Реалізується через Drift — 3 КБ без залежностей:
import Drift from 'drift-zoom';
new Drift(document.querySelector('.product-image-zoom img'), {
paneContainer: document.querySelector('.zoom-pane'),
inlinePane: false,
zoomFactor: 3,
hoverBoundingBox: true,
});
Для Drift зображення повинне мати атрибут data-zoom з URL зображення високої роздільної здатності:
<img src="<?= $previewPath ?>"
data-zoom="<?= $originalPath ?>"
alt="Товар">
<div class="zoom-pane"></div>
Вимоги до вихідних зображень
Зум добре працює лише якщо оригінальне зображення має достатню роздільну здатність. При масштабуванні 3x зображення 400×400 дасть лупу з 133×133 пікселів оригіналу — нечітко. Рекомендуваний мінімум для zoomFactor: 3 — оригінал 1600×1600px.
Якщо оригінали поступають в малій роздільній здатності, зум вимикається умовно:
$fileInfo = \CFile::GetFileArray($detailPictureId);
$showZoom = ($fileInfo['WIDTH'] >= 1200 && $fileInfo['HEIGHT'] >= 1200);
Галерея з зумом
Для карточок з кількома зображеннями (MORE_PHOTO) зум застосовується до активного зображення. При переключенні слайду необхідно переініціалізувати зум-інстанс з новим URL:
function switchImage(url, originalUrl) {
mainImg.src = url;
mainImg.dataset.zoom = originalUrl;
if (window.driftInstance) {
window.driftInstance.destroy();
}
window.driftInstance = new Drift(mainImg, driftOptions);
}
Ініціалізація зуму до завантаження зображення вызивает смещення — new Drift() необхідно викликати після img.onload або обертати в DOMContentLoaded. На тачскрин-пристроях hover не працює — потрібна окремої логіка tap-to-zoom або перехід до повноекранного просмотру через Fancybox з data-fancybox="gallery" на кожному елементі галерей.







