BetterTyped / react-zoom-pan-pinch

🖼 React library to support easy zoom, pan, pinch on various html dom elements like <img> and <div>
MIT License
1.46k stars 266 forks source link

Is there any way to do rotate in this library? #458

Open Tamagouuu opened 6 months ago

Tamagouuu commented 6 months ago

It will be good if the viewer have ability to rotate, isn't it?

hadarhubara10 commented 5 months ago

It is also necessary for me

guyzmo commented 3 months ago

I implemented rotation outside of the lib by doing something like this:

given the ref to an image:

  const imageRef = useRef<HTMLImageElement>(null)

I implemented and exposed the following API (through a custom context):

    const rotateClockwise = useCallback(() => {
      if (!imageRef?.current) return
      setRotation((rotation) => {
        const newRotation = (rotation + 90) % 360
        imageRef.current!.style.transform = `rotate(${newRotation}deg)`
        return newRotation
      })
    }, [setRotation, imageRef]);
    const rotateCounterClockwise = useCallback(() => {
      if (!imageRef?.current) return
      setRotation((rotation) => {
        const newRotation = (rotation - 90) % 360
        imageRef.current!.style.transform = `rotate(${newRotation}deg)`
        return newRotation
      })
    }, [setRotation, imageRef]);

Then I implemented it on the image itself:

  return (
      <TransformWrapper>
        <ImageControls />
        <TransformComponent>
          <img ref={imageRef} id="img" src={uri} />
        </TransformComponent>
      </TransformWrapper>
   )

then the ImageControls is just a custom version of the default Controls that implements both useControls() for the lib and my own context.

TBH, if I got little time, I believe it can be easy to add to the API

HTH

vojdan commented 1 month ago

This should be a pull request.

Trisogene commented 1 month ago

This solution doesnt update the trasform wrapper/component rotation thus it make the panning bugged. Im searching for an alternative solution, did anyone found something yet?

abrasumente999 commented 1 month ago

Setting the width and height in the wrapper and content wrapper with an !important fixed the panning issue for me, and centering the content with flex if your alignment is off.

const [rotation, setRotation] = React.useState(0);

const rotateClockwise = useCallback(() => {
    setRotation(rotation => {
        const newRotation = (rotation + 90) % 360;
        return newRotation;
     });
}, [setRotation]);

const rotateAnticlockwise = useCallback(() => {
    setRotation(rotation => {
        const newRotation = (rotation - 90) % 360;
        return newRotation;
    });
}, [setRotation]);

return (
    <TransformWrapper>
       <TransformComponent
           wrapperClass="!h-screen !w-screen"
           contentClass="!h-screen !w-full flex items-center justify-center"
        >
            <picture>
                <img
                   src={src}
                   style={{
                       objectFit: "cover",
                       maxHeight: "100vh",
                       maxWidth: "100vw",
                       transform: `rotate(${rotation}deg)`
                   }}
                />
            </picture>
        </TransformComponent>
     </TransformWrapper>

     <button onClick={() => rotateClockwise()} >Rotate clockwise</button>
     <button onClick={() => rotateAnticlockwise()} >Rotate Anticlockwise</button>
)