Реализация зума и панорамирования изображений в мобильном приложении

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.
Разработка и поддержка любых видов мобильных приложений:
Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Предлагаемые услуги
Показано 1 из 1 услугВсе 1735 услуг
Реализация зума и панорамирования изображений в мобильном приложении
Средняя
от 1 рабочего дня до 3 рабочих дней
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1052
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    445

Реализация зума и панорамирования изображений в мобильном приложении

Зум и пан выглядят как два gesture recognizer'а. На деле это связанная система трансформаций, которая должна работать плавно на 60 fps, не конфликтовать с другими жестами в приложении и корректно обрабатывать edge cases — двойное нажатие, границы изображения при панорамировании, возврат в исходное состояние.

Технические детали реализации

React Native — react-native-gesture-handler + react-native-reanimated. Стандартный <Image> не поддерживает трансформации через жесты — нужны Animated.Image или Reanimated. Подход с useSharedValue для scale и translate X/Y, useGestureHandler для PinchGesture + PanGesture:

const scale = useSharedValue(1);
const translateX = useSharedValue(0);
const translateY = useSharedValue(0);

const pinchGesture = Gesture.Pinch()
  .onUpdate((e) => {
    scale.value = clamp(savedScale.value * e.scale, 1, 5);
  })
  .onEnd(() => {
    savedScale.value = scale.value;
    if (scale.value < 1) {
      scale.value = withSpring(1);
    }
  });

Gesture.Simultaneous(pinchGesture, panGesture) — позволяет пинч и пан работать одновременно. Gesture.Race() — если нужно разделить их по приоритету.

Ограничение пана по границам изображения. При zoom x3 изображение 375px становится 1125px. Максимальный допустимый translateX = (scaledWidth - containerWidth) / 2. Без этой проверки пользователь утащит изображение за пределы экрана. Логика bounds checking реализуется в onUpdate через clamp():

const maxTranslateX = (containerWidth * (scale.value - 1)) / 2;
translateX.value = clamp(translateX.value + delta, -maxTranslateX, maxTranslateX);

Flutter — InteractiveViewer. Встроенный виджет Flutter с minScale, maxScale, boundaryMargin. Для базового кейса достаточно. Для галереи с несколькими изображениями — InteractiveViewer внутри PageView, но тут возникает конфликт: горизонтальный свайп для смены фото vs горизонтальный пан при зуме. Решение: InteractiveViewer перехватывает пан только когда scale > 1, при scale == 1 жест передаётся PageView.

iOS нативный — UIPinchGestureRecognizer + UIPanGestureRecognizer. gestureRecognizer.require(toFail:) для корректного разрешения конфликтов. CGAffineTransform для применения трансформаций к UIImageView. UIScrollView + UIScrollViewDelegate.viewForZooming — альтернатива, которая бесплатно даёт bounce при выходе за границы и zoomRect анимации.

Двойной тап

Двойное нажатие: если scale == 1 — зумим до 2–3x в точку касания. Если уже зумлено — возвращаем к scale == 1. Анимация через withSpring (для ощущения «резиновости») или withTiming с Easing.out(Easing.cubic).

Точка зума определяется из координат тапа относительно изображения:

const focalX = tapEvent.x - containerWidth / 2;
const focalY = tapEvent.y - containerHeight / 2;
translateX.value = withSpring(-focalX * (targetScale - 1));

Из практики: приложение просмотра медицинских снимков, React Native. Зум на рентгеновских снимках в высоком разрешении (4096×4096px). На Android загрузка полноразмерного изображения в Image компонент вызывала OutOfMemoryError. Решение: react-native-fast-image с resizeMode="contain" для превью + tile-based загрузка полноразмерного через react-native-zoom-toolkit с Deep Zoom format поддержкой.

Галерея с зумом

Галерея: FlatList горизонтальный с pagingEnabled={true} (или ViewPager на Android). Каждый элемент — зумируемое изображение. Конфликт жестов при горизонтальном пане — разруливаем через activeOffsetX в Pan gesture handler: пан активируется только при смещении > 10px по горизонтали, пока scale > 1 блокируем свайп страниц.

Что входит в работу

  • Pinch-to-zoom с ограничением min/max scale (обычно 1x–5x)
  • Pan при увеличенном изображении с ограничением по границам
  • Двойной тап — zoom in/out с анимацией в точку касания
  • Bounce-возврат при выходе за пределы границ
  • Интеграция в галерею/карусель с корректным разрешением конфликтов жестов
  • Поддержка высокоразрешённых изображений без OutOfMemoryError

Сроки

1–3 рабочих дня — одиночное изображение с зумом. С галереей и разрешением конфликтов жестов — 2–3 дня. Стоимость рассчитывается индивидуально.