Настройка лупы (magnifier) для изображений товаров 1С-Битрикс
Лупа работает только тогда, когда исходное изображение достаточно большое. На практике интернет-магазины загружают фото 800×800, включают magnifier, и пользователь при наведении видит размытый пиксельный квадрат — потому что библиотека пытается увеличить изображение, которого просто нет в нужном разрешении. Проблема не в JavaScript, а в том, как Битрикс хранит и ресайзит изображения.
Два изображения: отображаемое и зум-версия
Magnifier-библиотека (EasyZoom, Drift, jQuery Zoom) работает по одному принципу: в теге <img> — уменьшенная версия, в атрибуте data-zoom или href родительского элемента — большая. Если большой версии нет, лупа увеличивает то же самое маленькое изображение — результат неприемлемый.
В Битриксе для каждого изображения элемента инфоблока есть два поля: PREVIEW_PICTURE и DETAIL_PICTURE. Для magnifier нужен третий вариант — оригинал без ресайза. Стандартный компонент catalog.element прогоняет все изображения через CFile::ResizeImageGet(), который записывает уменьшенную копию в /upload/resize_cache/. Оригинал при этом остаётся в /upload/iblock/.
В шаблоне нужно передавать оба пути:
$fileId = $arResult['DETAIL_PICTURE']['ID'];
$fileInfo = \CFile::GetFileArray($fileId);
// Уменьшенная версия для отображения
$resized = \CFile::ResizeImageGet($fileId, ['width' => 600, 'height' => 600], BX_RESIZE_IMAGE_PROPORTIONAL);
// Оригинал для зума
$original = \CHTTP::URN2URI($fileInfo['SRC']);
Настройка порогового разрешения
Запускать magnifier на изображении 600×600 бессмысленно — зум-эффект появится только при коэффициенте увеличения меньше единицы. Реальный порог: оригинал должен быть минимум в 2× больше отображаемого. Проверка в шаблоне:
$zoomEnabled = ($fileInfo['WIDTH'] >= 1200 && $fileInfo['HEIGHT'] >= 1200);
Если изображение меньше — атрибут data-zoom не выводится, библиотека не инициализируется для этого элемента. Пользователь не видит сломанной лупы.
Подключение библиотеки через Assets Битрикса
Библиотеку нужно подключать через \Bitrix\Main\Page\Asset, а не хардкодить <script> в шаблоне — иначе при множественных компонентах на странице будет дублирование:
\Bitrix\Main\Page\Asset::getInstance()->addJs('/local/js/drift.min.js');
\Bitrix\Main\Page\Asset::getInstance()->addCss('/local/css/drift-basic.min.css');
Инициализация через inline-скрипт в конце шаблона:
document.querySelectorAll('.product-zoom-trigger').forEach(function(el) {
new Drift(el.querySelector('img'), {
paneContainer: document.querySelector('.product-zoom-pane'),
zoomFactor: 3,
hoverBoundingBox: true,
});
});
Галерея с несколькими изображениями
Когда у товара несколько фото (MORE_PHOTO), лупа должна пересоздаваться при смене активного изображения. Типовая ошибка — инициализация new Drift() один раз при загрузке. При клике на другую миниатюру экземпляр остаётся привязан к старому <img>, а в DOM уже новый элемент.
Правильно: хранить экземпляр в переменной и вызывать driftInstance.destroy() перед созданием нового при каждом переключении фото.
Мобильные устройства
На touch-экранах magnifier бесполезен — hover-события не работают. Вместо лупы нужен pinch-to-zoom. Библиотека PhotoSwipe решает обе задачи: на десктопе открывает полноэкранный просмотр с масштабированием, на мобильном поддерживает жесты. Drift и PhotoSwipe можно использовать одновременно: Drift — только на pointer: fine (мышь), PhotoSwipe — на pointer: coarse (touch). Это определяется через CSS media query @media (pointer: coarse) и аналогичную проверку в JS через window.matchMedia.







