Friday, 6 October 2023

How to export the Canvas as image using fabric.js and React

I am using fabric.js in react application . The scenario i was trying is i want to export the Entire canvas as image but below are the issues im getting

  1. Canvas is resetting after pressing export button.
  2. After zoomed or panned the i am unable to export the content which is outside viewport . I am able to export only which is viewable on screen .But i need to export entire object which are placed on the canvas irrespective of zoomed and pan .

below is my code

import React, { useEffect, useRef, useState } from 'react';
import { fabric } from 'fabric';

function CanvasComponent() {
  const canvasRef = useRef(null);
  const [fabricCanvas, setFabricCanvas] = useState(null);
  const [zoom, setZoom] = useState(1);

  useEffect(() => {
    const initCanvas = new fabric.Canvas(canvasRef.current);
    setFabricCanvas(initCanvas);

    // Set initial canvas size based on window
    const updateCanvasSize = () => {
      if (initCanvas) {
        const width = window.innerWidth;
        const height = window.innerHeight;
        initCanvas.setWidth(width);
        initCanvas.setHeight(height);
        initCanvas.renderAll();
      }
    };
    updateCanvasSize();

    // Add random objects
    const rect = new fabric.Rect({
      left: 100,
      top: 100,
      fill: 'red',
      width: 60,
      height: 70
    });

    const circle = new fabric.Circle({
      left: 200,
      top: 200,
      fill: 'green',
      radius: 50
    });

    initCanvas.add(rect, circle);

    // Add event listener for window resize
    window.addEventListener('resize', updateCanvasSize);

    // Clean up the event listener on component unmount
    return () => {
      window.removeEventListener('resize', updateCanvasSize);
    };

  }, []);


  useEffect(() => {
    if (fabricCanvas) {
      fabricCanvas.setZoom(zoom);
      fabricCanvas.renderAll();
    }
  }, [zoom, fabricCanvas]);

  const handleExport = () => {
    if (fabricCanvas) {
      // Store the current content of the canvas
      const originalData = fabricCanvas.toDataURL();

      // Fill the canvas with a white background
      const ctx = fabricCanvas.getContext('2d');
      ctx.fillStyle = 'white';
      ctx.fillRect(0, 0, fabricCanvas.width, fabricCanvas.height);

      // Draw the original content on top of the white background
      const img = new Image();
      img.onload = () => {
        ctx.drawImage(img, 0, 0);

        // Now export the canvas with the white background
        const dataURL = fabricCanvas.toDataURL('image/png');
        const link = document.createElement('a');
        link.href = dataURL;
        let file_name = (Math.random() + 1).toString(36).substring(7);
        link.download = `canvas_export_${file_name}.png`;
        link.click();

        // Restore the original content of the canvas
        fabricCanvas.clear();
        fabricCanvas.setBackgroundImage(originalData, fabricCanvas.renderAll.bind(fabricCanvas), {
          originX: 'left',
          originY: 'top'
        });
      };
      img.src = originalData;
    }
  };

  return (
    <div>
      <input 
        type="range" 
        min="0.1" 
        max="2" 
        step="0.1" 
        value={zoom} 
        onChange={(e) => setZoom(parseFloat(e.target.value))}
      />
      <button onClick={handleExport}>Export Canvas</button>
      <canvas ref={canvasRef}></canvas>
    </div>
  );
}

export default CanvasComponent;


from How to export the Canvas as image using fabric.js and React

No comments:

Post a Comment