iPhone 15 128 ГБ Green (Без коробки) – купить за 45 900 ₽ | CristalApple
Гарантия лучшей цены!

Гарантия лучшей цены!

Беcпроцентная рассрочка!

Беcпроцентная рассрочка!

Эксклюзивные предложения!

Эксклюзивные предложения!

(0)
Exclamation Icon НАЛИЧИЕ ТОВАРА УТОЧНЯЕТСЯ ПОСЛЕ ОФОРМЛЕНИЯ ЗАКАЗА

iPhone 15 128 ГБ Green (Без коробки)

Важное примечание
iPhone продается без предустановки приложения RuStore. Это обусловлено техническими ограничениями производителя Apple, которые не предоставляют возможность предустановки приложений из неизвестных источников на территории РФ. Приобретая данное устройство, вы соглашаетесь с тем, что уведомлены о наличии указанного ограничения. *Согласно ст. 4, 10 Закона РФ "О защите прав потребителей" №2300-1 от 07.02.1992г.
Apple Logo
Только оригинальные,
не восстановленные iPhone

Нет в наличии
Описание

Компактный. Красивый. Функциональный

Представленный осенью 2023 года iPhone 15 стал лучше во всех отношениях, сохранив привычные черты дизайна и компактные размеры. Он обзавёлся мощным процессором A16 Bionic, современной 48-Мегапиксельной камерой и динамическим островом, что делает его отличным вариантом для всех, кто не желает переплачивать за возможности Pro-серии.

Что нового?

В сравнении с iPhone 14, более новая модель получила матовое заднее стекло и новые расцветки, а вместо выреза в экране теперь используется динамический остров. На смену Lightning пришёл разъём USB-C: теперь заряжать MacBook, iPad и другие гаджеты можно одним кабелем. Более мощный и современный процессор обеспечивает новые возможности для приложений, использующих машинное обучение и улучшает алгоритмы камеры. Последняя также отличается более высоким разрешением и увеличенным сенсором.

Стоит только увидеть

iPhone 15 оснащен 6,1-дюймовым OLED-экраном Retina XDR Display. Этот дисплей поддерживает тактильную обратную связь, True Tone и защищен прочным стеклом Ceramic Shield. В отличие от iPhone 15 Pro здесь нет поддержки частоты обновления 120 Гц, но качеством изображения iPhone 15 радует не меньше: поддержка HDR, высокое разрешение и впечатляющая яркость заставят вас забыть о различиях, как только вы увидите этот экран в действии.

Селфи-монстр

Динамический остров iPhone 15 не только превращает скучный вырез в интерактивный элемент с тактильной отдачей, но и скрывает фронтальную камеру TrueDepth, также отвечающую за Face ID. Она примечательна автофокусом и способна записывать HDR-видео 4K в Dolby Vision с частотой до 60 к/с и до 30 к/с в режиме "Киноэффект". Фотографические стили и алгоритмы Deep Fusion и Smart HDR 5 обеспечат отличные селфи в любых условиях.

Новый уровень мобильной фотографии

Смартфон получил 48-Мегапиксельную основную камеру, которая порадует совершенно иным уровнем детализации. Вы также можете активировать режим 24 Мп, в котором смартфон будет делать два снимка и автоматически объединять их, сохраняя баланс между высокой светочувствительностью и потрясающей детализацией (в некоторых режимах автоматически включается 12 Мп). Как и при съёмке на фронтальную камеру, вы можете снимать 4K-видео в HDR и использовать "Киноэффект", а в режиме Action Mode айфон заменит экшн-камеру.

Простор для креативности

Для съёмки портретов больше не нужен отдельный режим – контрлируйте размытие заднего плана уже на готовых кадрах. Высокое разрешение основной камеры также позволяет приближать изображение в два раза без потери качества, что особенно полезно ввиду отсутствия отдельного телеобъектива. Дополнительный сверхширокоугольный модуль позволит делать отличные групповые снимки, снимать потрясающе динамичные видеоролики и делать эффектные пейзажи.

Удивительная автономность

Как и предыдущие модели, iPhone 15 поддерживает магнитные зарядные устройства MagSafe (до 15 ватт) и беспроводные зарядные устройства Qi (до 7,5 ватт). Смартфон оснащен емким аккумулятором, который обеспечивает до 80 часов прослушивания музыки и до 20 часов просмотра видео. Быстрая зарядка с использованием 20-ваттного адаптера (продается отдельно) позволяет зарядить устройство на 50% всего за 30 минут.

Показать полностью Свернуть
Характеристики
Тип товара
Смартфон
Бренд
Apple
Модель
iPhone 15
Память
128ГБ
Материал корпуса
Ceramic Shield/ стекло/ алюминий
Диагональ
6,1"
Емкость аккумулятора
3349 мАч
Платформа
iOS
Тип экрана
OLED
Цвет
Зеленый
Отзывы
Отзывов еще никто не оставлял
Написать отзыв Отмена
Оставить отзыв
Ранее просмотренные
Почему Cristal Apple
Более 12 лет                                                                               на рынке
Более 12 лет на рынке
Гарантия на каждый товар
Гарантия на каждый товар
3 физические точки продаж
3 физические точки продаж
Почему Cristal Apple
Возможность покупки в кредит
Возможность покупки в кредит
Бесплатная доставка по региону
Бесплатная доставка по региону
Самовывоз через 15 минут
Самовывоз через 15 минут
Гарантия лучшей цены
Гарантия лучшей цены
Опыт работы более 10 лет
Опыт работы более 10 лет
0
Navigation
Обратный звонок
Запрос успешно отправлен!
Имя *
Телефон *
Предзаказ
Предзаказ успешно отправлен!
Имя *
Телефон *
Добавить в корзину
Название товара
100 ₽
1 шт.
Перейти в корзину
$(function() { var isTouch = !!('ontouchstart' in window || navigator.msMaxTouchPoints); var mobile_point = 767; const isMobile = () => $(window).width() <= mobile_point; const isIOS = /iPhone|iPad|iPod/.test(navigator.userAgent); // ✅ ИСПРАВЛЕНИЕ: Определяем $widget в начале const $widget = $('.wt-widget-v4-collections-on-index'); if (isTouch) { $widget.find(".collection-preview").addClass("is-touch"); } $widget.each(function(index, el) { new LazyLoad({ container: $(el).get(0), elements_selector: '.lazyload', use_native: 'loading' in document.createElement('img') }); }); // ========== LIQUID GLASS DROP ========== function smoothStep(a, b, t) { t = Math.max(0, Math.min(1, (t - a) / (b - a))); return t * t * (3 - 2 * t); } function length(x, y) { return Math.sqrt(x * x + y * y); } function roundedRectSDF(x, y, width, height, radius) { const qx = Math.abs(x) - width + radius; const qy = Math.abs(y) - height + radius; return Math.min(Math.max(qx, qy), 0) + length(Math.max(qx, 0), Math.max(qy, 0)) - radius; } function texture(x, y) { return { x, y }; } class LiquidGlassDrop { constructor(container, sliderElement, splideInstance) { this.containerElement = container; this.sliderElement = sliderElement; this.splideInstance = splideInstance; this.splideTrack = sliderElement.querySelector('.splide__track'); this.splideList = sliderElement.querySelector('.splide__list'); this.canvasDPI = 1; this.id = 'liquid-glass-' + Math.random().toString(36).substr(2, 9); this.dragVelocity = 0; this.scaleMultiplier = 1; this.isIOS = isIOS; this.resizeObserver = null; this.currentVisibleSlide = null; this.listPadding = 16; // ✅ ИСПРАВЛЕНИЕ: Пиксельный буфер для SVG-фильтра (критично для iOS) this.filterBuffer = 20; this.container = this.containerElement.querySelector('.glass-drop'); this.dropContainer = this.containerElement.querySelector('.glass-drop-container'); // ✅ Проверка поддержки backdrop-filter const testElement = document.createElement('div'); testElement.style.backdropFilter = 'blur(1px)'; testElement.style.webkitBackdropFilter = 'blur(1px)'; this.supportsBackdropFilter = testElement.style.backdropFilter !== '' || testElement.style.webkitBackdropFilter !== ''; this.init(); } init() { // ✅ Показываем контейнер, если все готово this.dropContainer.style.display = 'block'; this.updateDimensions(); this.createElement(); this.updateShader(); this.setupResizeObserver(); this.startRenderLoop(); this.addClickHint(); this.setupDragHandler(); // Перенесли в init } updateDimensions() { // ✅ Ищем именно активный видимый слайд const activeSlide = this.sliderElement.querySelector('.splide__slide.is-active.is-visible'); const targetSlide = activeSlide || this.sliderElement.querySelector('.splide__slide.is-visible') || this.sliderElement.querySelector('.splide__slide'); if (targetSlide) { const slideRect = targetSlide.getBoundingClientRect(); // ✅ Капля должна быть чуть выше слайда const newWidth = Math.round(slideRect.width); const newHeight = Math.round(slideRect.height) + 35; // Добавляем 35px к высоте (больше снизу) const dimensionsChanged = this.width !== newWidth || this.height !== newHeight; this.width = newWidth; this.height = newHeight; this.currentVisibleSlide = targetSlide; this.radius = 37 / Math.max(this.width, this.height); document.documentElement.style.setProperty('--drop-width', `${this.width}px`); document.documentElement.style.setProperty('--drop-height', `${this.height}px`); // Обновляем размеры капли (самого div) this.dropContainer.style.width = `${this.width}px`; this.dropContainer.style.height = `${this.height}px`; if (dimensionsChanged && this.feImage) { this.updateSVGFilterDimensions(); } return dimensionsChanged; } else { // Fallback: используем размеры по умолчанию this.width = 140; this.height = 215; // 180 + 35 this.radius = 37 / Math.max(this.width, this.height); document.documentElement.style.setProperty('--drop-width', `${this.width}px`); document.documentElement.style.setProperty('--drop-height', `${this.height}px`); this.dropContainer.style.width = `${this.width}px`; this.dropContainer.style.height = `${this.height}px`; return false; } } // ✅ НОВЫЙ МЕТОД: Обновление размеров SVG фильтра с буфером для iOS updateSVGFilterDimensions() { const buffer = this.filterBuffer; const filter = this.svg.querySelector(`#${this.id}_filter`); if (filter) { // 1. Расширяем область фильтра на 2*buffer, чтобы избежать обрезки при трансформациях filter.setAttribute('width', (this.width + 2 * buffer).toString()); filter.setAttribute('height', (this.height + 2 * buffer).toString()); // 2. Сдвигаем область фильтра на -buffer, чтобы она была центрирована filter.setAttribute('x', `-${buffer}`); filter.setAttribute('y', `-${buffer}`); filter.setAttribute('primitiveUnits', 'userSpaceOnUse'); } if (this.feImage) { // feImage должен быть того же размера, что и элемент (без буфера) this.feImage.setAttribute('width', this.width.toString()); this.feImage.setAttribute('height', this.height.toString()); // 3. Сдвигаем feImage на +buffer, чтобы компенсировать сдвиг фильтра this.feImage.setAttribute('x', buffer.toString()); this.feImage.setAttribute('y', buffer.toString()); } this.canvas.width = this.width * this.canvasDPI; this.canvas.height = this.height * this.canvasDPI; this.updateShader(); } setupResizeObserver() { if ('ResizeObserver' in window) { this.resizeObserver = new ResizeObserver((entries) => { for (const entry of entries) { if (entry.target.classList.contains('splide__slide') || entry.target.classList.contains('splide__track')) { this.updateDimensions(); } } }); this.resizeObserver.observe(this.splideTrack); const slides = this.sliderElement.querySelectorAll('.splide__slide'); slides.forEach(slide => { this.resizeObserver.observe(slide); }); } } observeVisibleSlide() { // Отслеживаем именно активный видимый слайд const activeSlide = this.sliderElement.querySelector('.splide__slide.is-active.is-visible'); const visibleSlide = activeSlide || this.sliderElement.querySelector('.splide__slide.is-visible'); if (visibleSlide && visibleSlide !== this.currentVisibleSlide) { this.resize(); // Вызываем полную перерисовку/обновление размеров } } // ✅ Функция для определения активного слайда под каплей getActiveSlideUnderDrop() { if (!this.dropContainer) return null; const dropX = parseFloat(this.dropContainer.style.getPropertyValue('--drop-pos-x')) || 0; const dropWidth = parseFloat(this.dropContainer.style.getPropertyValue('--drop-width')) || 140; const dropCenter = dropX + dropWidth / 2; const slides = this.sliderElement.querySelectorAll('.splide__slide'); const trackRect = this.sliderElement.querySelector('.splide__track').getBoundingClientRect(); let closestSlide = null; let minDistance = Infinity; slides.forEach((slide) => { const slideRect = slide.getBoundingClientRect(); // slideCenter относительно trackRect.left const slideCenter = slideRect.left - trackRect.left + slideRect.width / 2; const distance = Math.abs(slideCenter - dropCenter); if (distance < minDistance) { minDistance = distance; closestSlide = slide; } }); return closestSlide; } // ✅ Функция для добавления подсказки о клике addClickHint() { if (!this.container) return; this.container.classList.add('show-click-hint'); const removeHint = () => { this.container.classList.remove('show-click-hint'); this.container.removeEventListener('click', removeHint); this.container.removeEventListener('touchstart', removeHint); }; this.container.addEventListener('click', removeHint); this.container.addEventListener('touchstart', removeHint); setTimeout(() => { this.container.classList.remove('show-click-hint'); }, 3000); } createElement() { // ✅ 1. Create SVG filter this.svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); this.svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg'); this.svg.setAttribute('width', '0'); this.svg.setAttribute('height', '0'); this.svg.style.cssText = 'position:fixed;top:0;left:0;pointer-events:none;z-index:9998;'; const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs'); const filter = document.createElementNS('http://www.w3.org/2000/svg', 'filter'); filter.setAttribute('id', `${this.id}_filter`); filter.setAttribute('filterUnits', 'userSpaceOnUse'); filter.setAttribute('colorInterpolationFilters', 'sRGB'); // ✅ Инициализируем фильтр с буфером для iOS const buffer = this.filterBuffer; filter.setAttribute('x', `-${buffer}`); filter.setAttribute('y', `-${buffer}`); filter.setAttribute('width', (this.width + 2 * buffer).toString()); filter.setAttribute('height', (this.height + 2 * buffer).toString()); filter.setAttribute('primitiveUnits', 'userSpaceOnUse'); this.feImage = document.createElementNS('http://www.w3.org/2000/svg', 'feImage'); this.feImage.setAttribute('id', `${this.id}_map`); this.feImage.setAttribute('width', this.width.toString()); this.feImage.setAttribute('height', this.height.toString()); this.feImage.setAttribute('x', buffer.toString()); // Сдвигаем feImage this.feImage.setAttribute('y', buffer.toString()); // Сдвигаем feImage this.feImage.setAttribute('result', 'map'); this.feDisplacementMap = document.createElementNS('http://www.w3.org/2000/svg', 'feDisplacementMap'); this.feDisplacementMap.setAttribute('in', 'SourceGraphic'); this.feDisplacementMap.setAttribute('in2', 'map'); this.feDisplacementMap.setAttribute('xChannelSelector', 'R'); this.feDisplacementMap.setAttribute('yChannelSelector', 'G'); this.feDisplacementMap.setAttribute('scale', '0'); filter.appendChild(this.feImage); filter.appendChild(this.feDisplacementMap); defs.appendChild(filter); this.svg.appendChild(defs); // ✅ 2. Create canvas this.canvas = document.createElement('canvas'); this.canvas.width = this.width * this.canvasDPI; this.canvas.height = this.height * this.canvasDPI; this.canvas.style.display = 'none'; this.context = this.canvas.getContext('2d'); // ✅ 3. Apply filter to glass-drop element if (this.container) { const filterURL = `url(#${this.id}_filter)`; this.container.style.webkitBackdropFilter = filterURL; this.container.style.backdropFilter = filterURL; this.container.style.isolation = 'isolate'; this.container.style.webkitTransform = 'translateZ(0)'; this.container.style.transform = 'translateZ(0)'; this.container.style.willChange = 'backdrop-filter, transform'; this.container.style.webkitBackfaceVisibility = 'hidden'; this.container.style.backfaceVisibility = 'hidden'; this.container.style.webkitPerspective = '1000'; this.container.style.perspective = '1000'; // ✅ Обработчик клика const clickHandler = (e) => { if (e.type.startsWith('touch') && this.dragVelocity > 5) return; e.preventDefault(); e.stopPropagation(); const activeSlide = this.getActiveSlideUnderDrop(); if (activeSlide) { const link = activeSlide.querySelector('.collection-link'); if (link) { this.container.classList.add('is-clicked'); setTimeout(() => { this.container.classList.remove('is-clicked'); window.location.href = link.getAttribute('href'); }, 150); } } }; this.container.addEventListener('click', clickHandler); this.container.addEventListener('touchend', clickHandler); } // ✅ 4. Append SVG и Canvas document.body.appendChild(this.svg); document.body.appendChild(this.canvas); } fragment(pos) { const { x, y } = pos; const normX = (x * 2 - 1) / this.scaleMultiplier; const normY = (y * 2 - 1) / this.scaleMultiplier; const normWidth = (this.width * this.scaleMultiplier) / Math.max(this.width, this.height) * this.radius; const normHeight = (this.height * this.scaleMultiplier) / Math.max(this.width, this.height) * this.radius; const normRadius = this.radius; const distanceToEdge = roundedRectSDF( normX, normY, normWidth * this.scaleMultiplier, normHeight * this.scaleMultiplier, normRadius ); const displacement = smoothStep(0.8, 0, distanceToEdge - 0.15); const scaled = smoothStep(0, 1, displacement); return texture(x * scaled + 0.5, y * scaled + 0.5); } updateShader() { const w = this.width * this.canvasDPI; const h = this.height * this.canvasDPI; const data = new Uint8ClampedArray(w * h * 4); let maxScale = 0; const rawValues = []; for (let i = 0; i < data.length; i += 4) { const x = (i / 4) % w; const y = Math.floor(i / 4 / w); const pos = this.fragment({ x: x / w, y: y / h }); const dx = pos.x * w - x; const dy = pos.y * h - y; maxScale = Math.max(maxScale, Math.abs(dx), Math.abs(dy)); rawValues.push(dx, dy); } maxScale *= 0.5; let index = 0; for (let i = 0; i < data.length; i += 4) { const r = rawValues[index++] / maxScale + 0.5; const g = rawValues[index++] / maxScale + 0.5; data[i] = r * 255; data[i + 1] = g * 255; data[i + 2] = 0; data[i + 3] = 255; } try { this.context.putImageData(new ImageData(data, w, h), 0, 0); this.feImage.setAttributeNS('http://www.w3.org/1999/xlink', 'href', this.canvas.toDataURL()); const baseScale = maxScale / this.canvasDPI; const velocityMultiplier = 0.05; const finalScale = baseScale * (1 + this.dragVelocity * velocityMultiplier); this.feDisplacementMap.setAttribute('scale', isNaN(finalScale) ? '0' : finalScale.toString()); } catch (error) { console.error('Shader update error:', error); } } updateDragState(velocity) { this.dragVelocity = Math.min(Math.abs(velocity), 50); this.scaleMultiplier = 1 + (this.dragVelocity * 0.005); if (this.container) { const scaleX = 1 + (this.dragVelocity * 0.01); const scaleY = 1 - (this.dragVelocity * 0.005); this.container.style.setProperty('--scale-x', scaleX); this.container.style.setProperty('--scale-y', scaleY); if (velocity !== 0) { this.container.classList.add('is-dragging'); } else { this.container.classList.remove('is-dragging'); } } this.updateShader(); } startRenderLoop() { const render = () => { this.observeVisibleSlide(); if (this.dragVelocity > 0.1) { this.dragVelocity *= 0.92; this.updateDragState(this.dragVelocity); } else if (this.dragVelocity > 0) { this.dragVelocity = 0; this.updateDragState(0); } requestAnimationFrame(render); }; requestAnimationFrame(render); } resize() { const changed = this.updateDimensions(); if (changed) { // SVG/Canvas удаляются/создаются заново только при изменении размеров слайда if (this.svg && this.svg.parentNode) { this.svg.remove(); } if (this.canvas && this.canvas.parentNode) { this.canvas.remove(); } this.createElement(); this.updateShader(); // Обновляем точки привязки после ресайза this.calculateSnapPoints(); this.updateDropPosition(this.splideInstance.index); } } // ============= DRAG LOGIC REFACTOR ============= calculateSnapPoints() { this.snapPoints = []; const track = this.sliderElement.querySelector('.splide__track'); if (!track) return; const trackRect = track.getBoundingClientRect(); const slides = this.sliderElement.querySelectorAll('.splide__slide'); slides.forEach((slide) => { const slideRect = slide.getBoundingClientRect(); // Позиция капли = (Центр слайда - Левый край трека) - (Ширина капли / 2) const dropX = (slideRect.left + slideRect.width / 2) - trackRect.left - (this.width / 2); this.snapPoints.push(dropX); }); // Устанавливаем ширину контейнера капли this.dropContainer.style.width = `${this.width}px`; } updateDropPosition(index) { if (this.snapPoints && this.snapPoints[index] !== undefined) { this.currentDropX = this.snapPoints[index]; this.dropContainer.style.setProperty('--drop-pos-x', `${this.currentDropX}px`); } } setupDragHandler() { const dropContainer = this.dropContainer; const splide = this.splideInstance; let isDragging = false; let startX = 0; let startDropX = 0; let lastTime = 0; let lastX = 0; let animationFrameId = null; let isSettling = false; let dragVelocity = 0; this.currentDropX = 0; this.calculateSnapPoints(); this.updateDropPosition(splide.index); // Начальная позиция const animateDrag = () => { if (!isDragging && !isSettling) { cancelAnimationFrame(animationFrameId); animationFrameId = null; return; } if (isDragging) { const currentTime = performance.now(); const deltaTime = currentTime - lastTime; if (deltaTime > 0) { dragVelocity = (this.currentDropX - lastX) / deltaTime * 100; // px/ms -> px/s } lastTime = currentTime; lastX = this.currentDropX; this.updateDragState(dragVelocity); } else if (isSettling) { dragVelocity *= 0.85; if (Math.abs(dragVelocity) < 0.5) { dragVelocity = 0; isSettling = false; } this.updateDragState(dragVelocity); } animationFrameId = requestAnimationFrame(animateDrag); } // DRAG START const startDrag = (e) => { if (isMobile() && e.type === 'mousedown') return; if (!isMobile() && e.type.startsWith('touch')) return; if (e.touches) { if (e.touches.length > 1) return; e.preventDefault(); } e.stopPropagation(); isDragging = true; isSettling = false; const clientX = e.touches ? e.touches[0].clientX : e.clientX; startX = clientX; startDropX = this.currentDropX; lastX = this.currentDropX; lastTime = performance.now(); this.container.style.transition = 'none'; dropContainer.style.transition = 'none'; if (!animationFrameId) { animateDrag(); } } // DRAG MOVE const drag = (e) => { if (!isDragging) return; const clientX = e.touches ? e.touches[0].clientX : e.clientX; const dx = clientX - startX; this.currentDropX = startDropX + dx; dropContainer.style.setProperty('--drop-pos-x', `${this.currentDropX}px`); // СИНХРОНИЗАЦИЯ СЛАЙДЕРА const dropCenter = this.currentDropX + (this.width / 2); let minDistance = Infinity; let closestIndex = -1; this.snapPoints.forEach((snapX, index) => { const snapCenter = snapX + (this.width / 2); const distance = Math.abs(dropCenter - snapCenter); if (distance < minDistance) { minDistance = distance; closestIndex = index; } }); // Двигаем слайдер, если капля сместилась к другому слайду if (closestIndex !== -1 && splide.index !== closestIndex) { splide.go(closestIndex); } if (e.type.startsWith('touch') && Math.abs(dx) > 10) { e.preventDefault(); } } // DRAG END const endDrag = (e) => { if (!isDragging) return; isDragging = false; isSettling = true; this.container.style.transition = ''; dropContainer.style.transition = ''; // Находим ближайшую точку для привязки капли let closestIndex = splide.index; // Анимируем каплю к точке привязки if (this.snapPoints[closestIndex] !== undefined) { this.currentDropX = this.snapPoints[closestIndex]; dropContainer.style.setProperty('--drop-pos-x', `${this.currentDropX}px`); } } // Инициализация событий dropContainer.addEventListener('mousedown', startDrag); window.addEventListener('mousemove', drag); window.addEventListener('mouseup', endDrag); window.addEventListener('mouseleave', endDrag); dropContainer.addEventListener('touchstart', startDrag, { passive: false }); window.addEventListener('touchmove', drag, { passive: false }); window.addEventListener('touchend', endDrag); // Обновление позиции капли при переключении слайдера splide.on('move', (newIndex) => { if (!isDragging) { this.updateDropPosition(newIndex); } }); // Пересчет точек при изменении размера window.addEventListener('resize', () => { setTimeout(() => { this.calculateSnapPoints(); this.updateDropPosition(splide.index); }, 100); this.resize(); }); } // ============= END DRAG LOGIC REFACTOR ============= } // ========== SLIDER INITIALIZATION (unchanged) ========== if (isMobile()) { let specialCollections = $widget.find(".js-collections"); let slider_mobile_right_padding; let slide_width_mobile; let slide_gap_mobile = specialCollections.find(".js-collections-slider").attr("data-slide-gap-mobile") / 2; $(window).on("resize", function() { slide_width_mobile = specialCollections.find(".splide__slide").width(); slider_mobile_right_padding = slide_width_mobile * 0.5 + slide_gap_mobile; specialCollections.find(".js-collections-slider").attr("data-mobile-right-padding", slider_mobile_right_padding); }); specialCollections.each(function() { let collections_block = $(this); let slider_block = collections_block.find(".js-collections-slider"); let slide_min_width = 160; let slide_min_width_mobile = 130; let slide_gap = 30; let slide_gap_mobile = 15; if (slider_block.is("[data-slide-min-width]")) { slide_min_width = parseInt(slider_block.attr("data-slide-min-width")); } else { slider_block.attr("data-slide-min-width", slide_min_width); } if (slider_block.is("[data-slide-min-width-mobile]")) { slide_min_width_mobile = parseInt(slider_block.attr("data-slide-min-width-mobile")); } else { slider_block.attr("data-slide-min-width-mobile", slide_min_width_mobile); } if (slider_block.is("[data-slide-gap]")) { slide_gap = parseInt(slider_block.attr("data-slide-gap")); } else { slider_block.attr("data-slide-gap", slide_gap); } if (slider_block.is("[data-slide-gap-mobile]")) { slide_gap_mobile = parseInt(slider_block.attr("data-slide-gap-mobile")); } else { slider_block.attr("data-slide-gap-mobile", slide_gap_mobile); } slide_width_mobile = slider_block.find(".splide__slide").width(); slider_mobile_right_padding = slide_width_mobile * 0.5 + slide_gap_mobile; slider_block.attr("data-mobile-right-padding", slider_mobile_right_padding); let slider = slider_block.splide({ type: "slide", drag: "free", snap: true, arrows: false, pagination: false, gap: slide_gap_mobile, padding: { right: slider_mobile_right_padding }, breakpoints: { 767: { arrows: false, gap: slide_gap_mobile, padding: { right: slider_mobile_right_padding }, }, }, }); configureSlider(slider, slider_block, slide_min_width, slide_min_width_mobile, slide_gap, slide_gap_mobile); // ✅ Инициализация Liquid Glass Drop только после монтирования Splide slider[0].splide.on('mounted', function() { if (isMobile()) { const dropInstance = new LiquidGlassDrop(collections_block[0], slider_block[0], slider[0].splide); slider_block.data('liquidGlassDrop', dropInstance); } }); // На случай, если Splide уже смонтирован if (slider[0].splide.root.classList.contains('is-initialized') && !slider_block.data('liquidGlassDrop')) { if (isMobile()) { const dropInstance = new LiquidGlassDrop(collections_block[0], slider_block[0], slider[0].splide); slider_block.data('liquidGlassDrop', dropInstance); } } }); } else { // Desktop initialization logic (без изменений) $widget.find(".js-collections-slider").each(function() { let slider_block = $(this); let slide_min_width = 160; let slide_min_width_mobile = 130; let slide_gap = 30; let slide_gap_mobile = 15; if (slider_block.is("[data-slide-min-width]")) { slide_min_width = parseInt(slider_block.attr("data-slide-min-width")); } if (slider_block.is("[data-slide-min-width-mobile]")) { slide_min_width_mobile = parseInt(slider_block.attr("data-slide-min-width-mobile")); } if (slider_block.is("[data-slide-gap]")) { slide_gap = parseInt(slider_block.attr("data-slide-gap")); } if (slider_block.is("[data-slide-gap-mobile]")) { slide_gap_mobile = parseInt(slider_block.attr("data-slide-gap-mobile")); } let slider = slider_block.splide({ type: "slide", arrows: true, pagination: false, gap: slide_gap, breakpoints: { 767: { arrows: false, gap: slide_gap_mobile, }, }, }); configureSlider(slider, slider_block, slide_min_width, slide_min_width_mobile, slide_gap, slide_gap_mobile); }); } function isMobileWidth() { return $(window).width() <= mobile_point; } function configureSlider(slider, sliderBlock, slide_min_width, slide_min_width_mobile, slide_gap, slide_gap_mobile) { let sliderInst = slider[0].splide; sliderInst.on("mounted", function() { sliderInst.go(0); recalcSlidesPerView(); displaySliderControls(slider); }); sliderInst.on("refresh", function() { recalcSlidesPerView(); displaySliderControls(slider); }); $(window).on("resize", function() { setTimeout(function() { if (sliderInst) { sliderInst.refresh(); // При ресайзе уведомляем каплю о необходимости обновления const dropInstance = sliderBlock.data('liquidGlassDrop'); if (dropInstance) { dropInstance.resize(); } } }, 0); }); function recalcSlidesPerView() { setTimeout(() => { let init_slide_min_width = isMobileWidth() ? slide_min_width_mobile : slide_min_width; let init_slide_gap = isMobileWidth() ? slide_gap_mobile : slide_gap; let new_per_page = getSlidesPerView(sliderBlock, init_slide_min_width, init_slide_gap); sliderInst.options = { perPage: new_per_page }; }, 0); } configureDragOption(slider); } function getSlidesPerView(sliderBlock, slideMinWidth, slideGap) { let right_padding = 0; if (sliderBlock.is("[data-mobile-right-padding]") && isMobileWidth()) { right_padding = parseInt(sliderBlock.data("mobileRightPadding")) + slideGap; } return Math.floor((sliderBlock.width() + slideGap - right_padding) / (slideMinWidth + slideGap)); } function displaySliderControls(slider) { let sliderInst = slider[0].splide; let collections = slider.parents(".js-collections"); let slider_arrow = collections.find(".collections__slider-arrow"); if (sliderInst.length <= sliderInst.options.perPage) { slider_arrow.addClass("is-hide"); slider.addClass("is-hide-paging"); } else { slider_arrow.removeClass("is-hide"); slider.removeClass("is-hide-paging"); } } function configureDragOption(slider) { if (slider[0].splide.length <= slider[0].splide.options.perPage) { slider.splide().options = { drag: false }; } } });
Заявка

Я ознакомлен и согласен с условиями оферты и политики конфиденциальности.

Заказ в один клик

Я ознакомлен и согласен с условиями оферты и политики конфиденциальности.