Смартфон iPhone 14 Pro 256 ГБ Gold (Без коробки) – купить за 75 900 ₽ | CristalApple
Гарантия лучшей цены!

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

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

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

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

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

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

Смартфон iPhone 14 Pro 256 ГБ Gold (Без коробки)

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

PROсто невероятный

Безупречный дизайн. Невероятная камера. Потрясающий экран с функцией Always -On Display и магия Apple, которая превращает обычный вырез в дисплее в уникальный интерактивный элемент – всё это iPhone 14 Pro. Cмартфон получил новый процессор, сделанный по самым современным технологиям, а возможности для съёмки шагнули далеко как никогда раньше. С новыми функциями iOS и всеми технологиями, унаследованными от предыдущих моделей линейки Pro, смартфон поражает воображение.

Поражает с первого взгляда

Производительность, возможности камер и дизайн iPhone 14 Pro и iPhone 14 Pro Max не отличаются. Оба смартфона получили уже знакомые очертания и рамку из идеально отполированной хирургической стали. Дисплей защищает сверхпрочное стекло Ceramic Shield, а задняя часть из матового стекла не только смотрится эффектно, но и ощущается очень приятно, когда устройство лежит в руке. Одинаковая толщина рамок по периметру экрана придаёт смартфону более законченный внешний вид, чем у предыдущих моделей, а любая из четырёх расцветок смотрится очень эффектно.

Ярче Солнца

6,1-дюймовый OLED-экран iPhone 14 Pro стал гораздо ярче, что особенно хорошо ощущается при использовании смартфона днём. Яркость на улице достигает невероятных 2000 нит, поэтому даже в яркий солнечный день всё отлично видно. Не забыли и про комфорт для любителей кино и сериалов: пиковая яркость при просмотре HDR-контента составляет 1600 нит. Кроме того, дисплей поддерживает True Tone, динамическую частоту обновления с технологией ProMotion и отличается потрясающей контрастностью 2000000:1.

Чудо-остров

При всех достоинствах экрана iPhone 14 Pro, первое что бросается в глаза – это новый вырез камеры TrueDepth и соседствующих с ней датчиков, который теперь расположен прямо в экране и называется "Динамическим островом". Он не только занимает меньше места, но и всячески обыгрывается в системе. Уведомления, всплывающие окна и фоновые приложения превращают обычный вырез в центральный элемент интерфейса iOS с традиционной для Apple приятной анимацией, оптимизированной под частоту обновления экрана, которая может достигать 120 Гц.

Полный контроль над перспективой

Новый сенсор основной камеры позволяет увеличивать изображение в 2 раза баз потери качества. Таким образом, теперь доступен быстрый выбор: 0,5X, 1X, 2X и 3X. Телефотокамера с 3-кратным зумом обеспечивает не только возможность приближения без потери качества, но и открывает массу творческих возможностей при съёмке портретов. Более того, отличный портрет можно снять на любую из камер, благодаря LiDAR и TrueDepth. Широкоугольная камера с увеличенным сенсором и поддержкой макросъёмки получила улучшенный автофокус, а фронтальная камера TrueDepth может похвастаться новой оптикой с диафрагмой ƒ/1.9 и получила автофокус. Фотографические стили, поддержка ProRAW и эффекты студийного освещения помогут сделать потрясающие кадры на любую из камер.

Невероятно чёткие снимки

Камера iPhone 14 Pro – это огромный шаг вперёд. Огромный 48-Мегапиксельный сенсор основной камеры получил впечатляющие размеры – 1/1.28". Он обеспечивает невероятную детализацию днём и повышенную светочувствительность ночью, благодаря объединению пикселей и новой технологии вычислительной фотографии Photonic Engine c усовершенствованными алгоритмами Smart HDR 4. Улучшилась и система автофокуса, теперь каждый пиксель матрицы участвует в работе системы фокусировки, что повышает её точность и скорость. В результате мобильная фотография выходит на новый уровень.

Снимайте как оператор из Голливуда

На новый уровень выходит и съёмка видео на iPhone. Объединение пикселей сенсора, в сочетании с новыми возможностями процессора A16 повышает качество при записи в условиях низкой освещённости. Новый уровень производительности открывает доступ к функции Action Mode – теперь можно записывать невероятно плавное видео в разрешении 2,8K, а "Киноэффект" стал доступен и в 4K при 24 или 30 кадрах в секунду. Не стоит забывать и о возможности записи в формате ProRes, который дат больше возможностей для постобработки. Примечательно, что запись в данном формате, как и режим "Киноэффект", а также поддержка Dolby Vision HDR работают на всех камерах смартфона.

 

Всегда полная батарея

Процессор A16 Bionic, сделанный по техпроцессу 4нм, не только повышает производительность и открывает доступ к новым возможностям, но и продлевает время работы устройства за счёт повышенной энергоэффективности. Довольно ёмкий аккумулятор, в сочетании с быстрой зарядкой (до 50% за полчаса при использовании доступного отдельно 20-Ваттного адаптера), поддержка ЗУ MagSafe (до 15 Ватт) и беспроводных устройств стандарта Qi, которые могут быть встроены в лампы, столы, держатели и другие предметы, позволяют подобрать аксессуары таким образом, чтобы процесс зарядки смартфона стал практически незаметным.

Вместе веселее

Любой iPhone – это не только безупречный дизайн, отличная камера и максимум комфорта, но и огромные возможности iOS, которые по-настоящему раскрываются в связке с другими гаджетами Apple. Помимо уже знакомых многим облачных функций iCloud и возможностям Handoff, AirPlay, AirDrop и другим приятным особенностям экосистемы, Apple добавили возможность использовать смартфон как веб-камеру для Mac, а наушники AirPods Pro 2-го поколения теперь могут улучшить звук на основе трёхмерного снимка головы, который используется для Face ID, а с новыми обновлениями уникальных и полезных особенностей будет ещё больше.

Показать полностью Свернуть
Характеристики
Бренд
Apple
Модель
iPhone 14 Pro
Память
256ГБ
Цвет
Золотой
Отзывы
Отзывов еще никто не оставлял
Написать отзыв Отмена
Оставить отзыв
Ранее просмотренные
Почему 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 }; } } });
Заявка

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

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

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