Home » Create Image Zoom Component in React JS

Create Image Zoom Component in React JS

how to create image zoom component react js

In this tutorial, we are going to explore how to create an image zoom component in React JS. Zoomable image components can be very useful in various situations, such as image galleries, displaying scientific diagrams, etc.

We will not be using any library instead, we will be creating our own custom component to zoom in and zoom out an image in React.

As you can see in the above video, we have displayed an image and there are two buttons for zoom in and zoom out. The user can also drag the image to see more details.

How to Create Zoomable Image Component in React JS

First, we will create our `ImageZoomInOut` component, which takes `imageUrl` as a prop. Then we define the required state variables.

Defining state variables

const [scale, setScale] = useState(1);
const [position, setPosition] = useState({ x: 0, y: 0 });
const imageRef = useRef(null);

The `scale` state variable holds the current scale value of the image, while the `position` variable holds the current position of the image. `imageRef` is a reference to the `img` element that we will render later.

Defining zoom in/out functions

const handleZoomIn = () => {
   setScale((scale) => scale + 0.1);
};

const handleZoomOut = () => {
   setScale((scale) => scale - 0.1);
};

In the above code, we have defined two functions that handle the zoom-in/out functionality. When the `handleZoomIn` function is called, it increases the `scale` value by 0.1, and when the `handleZoomOut` function is called, it decreases the `scale` value by 0.1.

Defining mouse event listeners with the useEffect hook

  useEffect(() => {
    const image = imageRef.current;
    let isDragging = false;
    let prevPosition = { x: 0, y: 0 };

    const handleMouseDown = (e) => {
      isDragging = true;
      prevPosition = { x: e.clientX, y: e.clientY };
    };

    const handleMouseMove = (e) => {
      if (!isDragging) return;
      const deltaX = e.clientX - prevPosition.x;
      const deltaY = e.clientY - prevPosition.y;
      prevPosition = { x: e.clientX, y: e.clientY };
      setPosition((position) => ({
        x: position.x + deltaX,
        y: position.y + deltaY,
      }));
    };

    const handleMouseUp = () => {
      isDragging = false;
    };

    image?.addEventListener("mousedown", handleMouseDown);
    image?.addEventListener("mousemove", handleMouseMove);
    image?.addEventListener("mouseup", handleMouseUp);

    return () => {
      image?.removeEventListener("mousedown", handleMouseDown);
      image?.removeEventListener("mousemove", handleMouseMove);
      image?.removeEventListener("mouseup", handleMouseUp);
    };
  }, [imageRef, scale]);

Here, we use the useEffect hook to add mouse event listeners to the `img` element. When the component mounts, the useEffect function is called, and the mouse event listeners are attached to the `img` element referenced by `imageRef`.

The `handleMouseDown` function sets a flag indicating that the image is being dragged, and the current position of the mouse. The `handleMouseMove` function calculates the change in the position of the mouse and updates the position of the image accordingly using the `setPosition`

The `handleMouseUp` function resets the drag flag. We remove the mouse event listeners when the component unmounts

Render image and buttons for zooming in and out

  return (
    <div
      style={{
        backgroundColor: "#ffffff",
        borderRadius: "10px",
        position: "relative",
        overflow: "hidden",
      }}
    >
      <div className="btn-container">
        <button onClick={handleZoomIn}>
          <span class="material-symbols-outlined">add</span>
        </button>
        <button onClick={handleZoomOut}>
          <span class="material-symbols-outlined">remove</span>
        </button>
      </div>

      <img
        ref={imageRef}
        src={imageUrl}
        alt=""
        style={{
          width: "50vw",
          height: "auto",
          transform: `scale(${scale}) translate(${position.x}px, ${position.y}px)`,
          cursor: "move",
        }}
        draggable={false}
      />
    </div>
  );

The above JSX code renders the image element and two buttons for zooming in and out. The image element has a `ref` attribute that references the `imageRef` variable, which is used to access the image element in the `useEffect` hook.

We set the `draggable` attribute to false to prevent the default behavior of dragging and dropping the image.

Complete code of `ImageZoomInOut` component:

import React, { useState, useRef, useEffect } from "react";


function ImageZoomInOut({ imageUrl }) {
  const [scale, setScale] = useState(1);
  const [position, setPosition] = useState({ x: 0, y: 0 });
  const imageRef = useRef(null);

  const handleZoomIn = () => {
    setScale((scale) => scale + 0.1);
  };

  const handleZoomOut = () => {
    setScale((scale) => scale - 0.1);
  };

  useEffect(() => {
    const image = imageRef.current;
    let isDragging = false;
    let prevPosition = { x: 0, y: 0 };

    const handleMouseDown = (e) => {
      isDragging = true;
      prevPosition = { x: e.clientX, y: e.clientY };
    };

    const handleMouseMove = (e) => {
      if (!isDragging) return;
      const deltaX = e.clientX - prevPosition.x;
      const deltaY = e.clientY - prevPosition.y;
      prevPosition = { x: e.clientX, y: e.clientY };
      setPosition((position) => ({
        x: position.x + deltaX,
        y: position.y + deltaY,
      }));
    };

    const handleMouseUp = () => {
      isDragging = false;
    };

    image?.addEventListener("mousedown", handleMouseDown);
    image?.addEventListener("mousemove", handleMouseMove);
    image?.addEventListener("mouseup", handleMouseUp);

    return () => {
      image?.removeEventListener("mousedown", handleMouseDown);
      image?.removeEventListener("mousemove", handleMouseMove);
      image?.removeEventListener("mouseup", handleMouseUp);
    };
  }, [imageRef, scale]);

  return (
    <div
      style={{
        backgroundColor: "#ffffff",
        borderRadius: "10px",
        position: "relative",
        overflow: "hidden",
      }}
    >
      <div className="btn-container">
        <button onClick={handleZoomIn}>
          <span class="material-symbols-outlined">add</span>
        </button>
        <button onClick={handleZoomOut}>
          <span class="material-symbols-outlined">remove</span>
        </button>
      </div>

      <img
        ref={imageRef}
        src={imageUrl}
        alt=""
        style={{
          width: "50vw",
          height: "auto",
          transform: `scale(${scale}) translate(${position.x}px, ${position.y}px)`,
          cursor: "move",
        }}
        draggable={false}
      />
    </div>
  );
}

export default ImageZoomInOut;

Also check out:

Using the `ImageZoomInOut` component in App.js

import React from 'react'
import ImageZoomInOut from './ImageZoomInOut'

const IMAGE_URL = 'YOUR_IMAGE_PATH_HERE'

function App() {
  return (
    <div>
      <ImageZoomInOut imageUrl={IMAGE_URL} />
    </div>
  )
}

export default App

Here, we are passing a prop named `imageUrl` to the `ImageZoomInOut` component, which is a string containing the URL of the image we want to display and zoom. The `imageUrl` prop is then received and used in the `img` tag inside the `ImageZoomInOut` component to display the image.

By rendering the `ImageZoomInOut` component with the appropriate `imageUrl` prop, we can easily display and interact with the zoomable image component in our application.

Output:

zoomable image component in react js

Conclusion

That’s it, we have created our zoomable image component in React JS. This component allows users to zoom in and out of an image using buttons and drag the image to reposition it. You can also try to customize this component by adding more functionalities.

Leave a Reply

Your email address will not be published.