rubenmondom
rubenmondom

Reputation: 103

Zoom with different scales in swiper

Is there any way to zoom.in() and zoom.out() at different levels of zoom, instead of have zoom (zoom.in) or not have zoom (zoom.out)? The problem is that I want different levels of zoom, like 100%-150%-200%-250%-300% (100% = minRatio, 300% = maxRatio), when I'm zooming, and not to get the maxRatio zooming when I zoom.in(), I would like to be able to go by steps.

I've found this solution: Zoom in on a mousewheel point (using scale and translate) using js + css, but I think that this feature should be included in the library, instead of doing it by hand.

Upvotes: 2

Views: 1854

Answers (1)

stu197188
stu197188

Reputation: 11

I needed to achieve this for a React app and managed to do so writing a custom module which extended the Zoom module functionality - sure you could use a similar approach for whatever implementation you needed...

// ExtendedZoom.ts

const ExtendedZoom = (_ref: Ref) => {
  const { swiper } = _ref;
  const gesture: GestureElements = {};

  const setZoom = (scale: number) => {
    gesture.slideEl = swiper.slides[swiper.activeIndex] as HTMLDivElement;

    if (!swiper.params || typeof swiper.params.zoom !== 'object') return;

    gesture.imageEl = gesture.slideEl.querySelector(
      `.${swiper.params.zoom.containerClass} img`,
    ) as HTMLImageElement;
    gesture.imageWrapEl = gesture.imageEl.closest(
      `.${swiper.params.zoom.containerClass}`,
    ) as HTMLDivElement;

    if (swiper.params.zoom.zoomedSlideClass) {
      gesture.slideEl.classList.add(swiper.params.zoom.zoomedSlideClass);
    }

    swiper.zoom.scale = scale;

    gesture.imageWrapEl.style.transition = '0.3s';
    gesture.imageWrapEl.style.transform = 'translate(0, 0)';

    gesture.imageEl.style.transition = '0.3s';
    gesture.imageEl.style.transform = `translate(0, 0) scale(${swiper.zoom.scale})`;
  };

  swiper.zoom.setZoom = setZoom;
};

export default ExtendedZoom;
// ComponentUsingSwiper.tsx

import React, { useState, useMemo } from 'react';
import { Swiper, SwiperSlide } from 'swiper/react';
import { Keyboard, Zoom } from 'swiper';
import { ZoomOptions } from 'swiper/types';

import ExtendedZoom from './ExtendedZoom';

const WithZoomModules = [Keyboard, Zoom, ExtendedZoom];
const MAX_ZOOM = 4;

const WithIncrementalZoom: React.FC<{ images: Image[] }> = ({
  images,
}) => {
  const [swipeNavEnabled, setSwipeNavEnabled] = useState(true);
  const [activeZoomScale, setActiveZoomScale] = useState(1);

  const zoomConfig = useMemo<ZoomOptions>(
    () => ({
      containerClass: 'swiper-zoom-container',
      minRatio: 1,
      maxRatio: activeZoomScale < MAX_ZOOM ? activeZoomScale + 1 : MAX_ZOOM,
    }),
    [activeZoomScale],
  );

  const onZoomChange = (swiper: SwiperInstanceProps, scale: number) => {
    if (scale === 1 && !swipeNavEnabled) setSwipeNavEnabled(true);
    if (scale > 1 && swipeNavEnabled) setSwipeNavEnabled(false);

    setActiveZoomScale(scale);
  };

  return (
    <Swiper
      slidesPerView={1}
      modules={WithZoomModules}
      loop
      keyboard
      onSlideChange={onSlideChange}
      zoom={zoomConfig}
      allowTouchMove={swipeNavEnabled}
      onZoomChange={onZoomChange}
    >
      {images.map((image) => (
         <SwiperSlide key={image.href}>
           <div className="swiper-zoom-container">
             <img src={image.href} alt={image.caption} />
           </div>
         </SwiperSlide>
      ))}
      <ZoomControls maxZoom={MAX_ZOOM} activeZoomScale={activeZoomScale} />
   </Swiper>
  );
};
// ZoomControls.tsx

const ZoomControls: React.FC<{ maxZoom: number, activeZoomScale: number }> = ({ maxZoom, activeZoomScale }) => {

  const swiper = useSwiper();

  const zoomIn = () => {
    if (activeZoomScale < maxZoom) {
      swiper.zoom.setZoom(activeZoomScale + 1);
    }
  };

  const zoomOut = () => {
    if (activeZoomScale > 1) {
      swiper.zoom.setZoom(activeZoomScale - 1);
    }
  };

  return (
    <>
      <button type="button" onClick={zoomIn}>Zoom In</button>
      <button type="button" onClick={zoomOut}>Zoom Out</button>
    </>
  );
}

Upvotes: 1

Related Questions