The buyer wants to inspect the product from all sides before ordering. A typical gallery of 8 photos cannot replace the ability to rotate the object. 360-degree viewing is a sequence of frames (24-72 shots) that, when dragged, create the illusion of rotation. Implementing 360 photos on Bitrix is a non-trivial engineering task: you need to design a storage scheme, choose a player, ensure fast loading on mobile devices. The result of a proper implementation is reduced returns and increased conversion. Usually stores face problems: slow loading, lack of touch support, difficulty updating frames. We solve these problems comprehensively. We will set up 360 photos on 1С-Битрикс turnkey: implement storage, player, preloading, and WebP optimization. Order the setup — contact us.
Setting up 360 product photos on 1С-Битрикс
360 frames are stored as regular images attached to the product via an infoblock property of type File (F) with the "Multiple" flag. The property is created with a code, e.g., IMAGES_360.
When adding frames through the admin panel, they are saved in b_iblock_element_property with PROPERTY_TYPE = 'F' — each frame as a separate row with a common IBLOCK_ELEMENT_ID and IBLOCK_PROPERTY_ID.
Retrieving frames for the frontend:
$element = \CIBlockElement::GetByID($productId)->GetNextElement(); $props = $element->GetProperties(); $frames = $props['IMAGES_360']['VALUE']; // $frames — array of file IDs from b_file $frameUrls = array_map(function($fileId) { return \CFile::GetPath($fileId); }, (array)$frames); // Pass to JSON for JS player echo json_encode(['frames' => $frameUrls]); Comparison of storage methods
| Method | Number of DB entries | Management complexity | Flexibility |
|---|---|---|---|
| Multiple file property | N entries per product | Low | Low |
| Separate 360 infoblock | 1 entry per set + links | Medium | High |
If you have a catalog with thousands of SKUs, the second method is preferable: it allows reusing one set of frames for multiple products and centrally managing loading.
JavaScript player for 360: which to choose?
The simplest implementation without third-party libraries is on Canvas or CSS background-position. For production, use one of the ready-made solutions:
| Player | Technology | Touch support | Size | Features |
|---|---|---|---|---|
| CSS sprite | CSS background-position | Yes | ~5 KB | Requires frame stitching |
| Canvas | JavaScript + Canvas | Yes | ~8 KB | Flexible rendering |
| three-sixty.js | jQuery plugin | Yes | ~20 KB | Drag, pinch, inertia |
CSS sprite is the lightest but requires preprocessing. Canvas gives more control. three-sixty.js is a full-featured solution with inertia and zoom, but depends on jQuery.
Implementation based on CSS sprite (when all frames are stitched into one horizontal sprite):
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; } } } Initialization in the bitrix:catalog.element component template:
new Viewer360( document.getElementById('viewer-360'), <?= json_encode($frameUrls) ?> ); Preloading is mandatory for UX
With lazy loading of frames, the rotation will lag on the first scroll. The correct approach is to preload all frames in the background after page load:
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(() => { // Unlock controls after loading document.getElementById('viewer-360').classList.remove('loading'); }); Until preloading is complete, the container is blocked with a spinner.
Preloading details
We use progressive loading: the first frame is displayed immediately, the rest are loaded in the background. This reduces time to first interaction by 2-3 times compared to full loading of all frames before display. On mobile devices, we additionally reduce frame resolution to 600×450 pixels.Optimization: WebP and frame size
36 frames at 800×600px in JPEG 80% quality = ~3-5 MB total weight. For mobile networks, this is a lot. Optimization:
- Conversion to WebP — compression 25-35% better than JPEG at the same visual quality.
- Reducing frame resolution to 600×450 — sufficient for 360 rotation.
- Progressive loading: first show the first frame, the rest in the background.
Bitrix generates WebP via \CFile::ResizeImageGet() with the parameter 'format' => 'webp' starting from certain versions. For older versions, an external converter via exec('cwebp ...') during image upload. More details in the documentation.
Deliverables included
- Creating an infoblock or property for storing 360 frames with migrations.
- Ready JavaScript player with preloading and touch support.
- WebP converter (if needed) and resize settings.
- Integration into the standard
bitrix:catalog.elementcomponent. - Testing on real products.
- Documentation for frame upload and configuration.
- Post-release support for one month.
- Training for your team on maintaining the 360 system.
Company metrics and experience
With over 5 years of experience in Bitrix development and 50+ successful 360 implementations, we guarantee a smooth process. Our team has delivered 100+ e-commerce projects, reducing bounce rates by an average of 15% after implementing 360 views. Typical project cost starts from $500, and bandwidth savings from WebP conversion average 30%.
How we do it: process and timeline
We don't just insert ready-made code — we adapt the solution to your catalog, load, and product types. Stages:
- Audit of the current catalog and infrastructure.
- Designing the storage scheme (property or separate infoblock).
- Integrating a JavaScript player with touch and drag handling.
- Image optimization (WebP, resize, progressive loading).
- Testing on mobile and desktop.
- Deployment and documentation handover.
Estimated timeline: from 3 to 7 working days depending on catalog volume. Exact timeline is calculated after analysis. Get a consultation from an engineer — contact us.

