javascriptreactjsfabricjs

How to image upload in Fabric js canva with react


I am using Fabric js v 6 in React app. I am trying to upload my image from a url but not able to do so. I am not getting any error as well whenever I click in the image the addImageToCanvas gets called but inside it FabricImage.fromURL() function does not gets call at all. So I am seeing in my console log

Attempting to load image:", imagePath

const addImageToCanvas = useCallback(
    (imageName: string) => {
      if (!fabricCanvasRef.current) {
        console.error("Canvas reference is not available");
        return;
      }

      const canvas = fabricCanvasRef.current as Canvas;
      const imagePath = `http://localhost:5173/public/image/${imageName}`;
      console.log("Attempting to load image:", imagePath);

      FabricImage.fromURL(
        imagePath,
        (img: FabricImage) => {
          console.log("Image loaded successfully:", img);
          if (!img) {
            console.error("Failed to load image:", imagePath);
            return;
          }

          img.set({
            left: 0,
            top: 0,
            scaleX: 0.5,
            scaleY: 0.5,
          });

          canvas.add(img);
          canvas.renderAll();
          console.log("Image added to canvas");
        },
        {
          crossOrigin: "anonymous",
        }
      );
    },
    [fabricCanvasRef]
  );

How do I get the image in my canva in fabric js whose version is 6


Solution

  • You can try this code and just turn it to typescript .

        import React, { useState, useRef, ChangeEvent } from 'react';
    import { Canvas, Image as FabricImage } from 'fabric';
    
    interface ImageElementProps {
      canvas: Canvas;
      canvasRef: React.RefObject<HTMLCanvasElement>;
    }
    
    const ImageElement: React.FC<ImageElementProps> = ({ canvas, canvasRef }) => {
      const [imageSrc, setImageSrc] = useState<string | null>(null);
      const [image, setImage] = useState<FabricImage | null>(null);
      const [uploadMessage, setUploadMessage] = useState<string>("Upload Image");
      const imageUploadRef = useRef<HTMLInputElement>(null);
    
      const imageUpload = (e: ChangeEvent<HTMLInputElement>) => {
        const file = e.target.files?.[0];
        console.log(file);
        if (file) {
          const url = URL.createObjectURL(file);
          console.log(url);
          setImageSrc(url);
          setUploadMessage("Change Image");
    
          const ImageElement = new Image();
          ImageElement.src = url;
          ImageElement.crossOrigin = "anonymous";
          ImageElement.onload = () => {
            console.log("Image Loaded");
            const imageWidth = ImageElement.width;
            const imageHeight = ImageElement.height;
            const canvasWidth = canvasRef.current?.width ?? 0;
            const canvasHeight = canvasRef.current?.height ?? 0;
            const scale = Math.min(
              canvasWidth / imageWidth,
              canvasHeight / imageHeight
            );
            const fabricImage = new FabricImage(ImageElement, {
              left: 0,
              top: 0,
              scaleX: scale,
              scaleY: scale,
            });
            setImage(fabricImage);
            canvas.add(fabricImage);
            canvas.renderAll();
          };
          ImageElement.src = url;
        }
      };
    };
    
    export default ImageElement;
    

    The changes done in the code

    what i have done here in the code is that

    Image Upload and Processing:

    The imageUpload function handles file selection and image processing. It creates an object URL for the selected file and updates the component state. A new Image object is created to load the image and calculate its dimensions.

    Canvas Integration:

    The code uses the fabric.js library to create and manipulate images on a canvas so I make a image element first and then with that Image element.It calculates the appropriate scale to fit the image within the canvas dimensions and in FabricImage we create a new image using this FabricElement.

    Then we add the created image to canva using canvas.add and then renderAll on the screen.