javascriptreactjsnext.jsfabricjs

fabricjs: how to use loadSVGFromURL with react useEffect?


I tried to render a SVG onto my canvas using useEffect, like this:

// store canvas reference
const [canvas, setCanvas] = useState<fabric.Canvas>();
    useEffect(() => {
        const c = new fabric.Canvas("canvas", {
          height: 700,
          width: 700,
          backgroundColor: "white",
        });
        setCanvas(c);
        c.renderAll();
        return () => {
          c.dispose();
        };
      }, []);

    useEffect(() => {
      fabric.loadSVGFromURL('/example.svg', (objects, options) => {
        const svg = fabric.util.groupSVGElements(objects, options);
        // Add the SVG to the canvas and render
        canvas?.add(svg);
        canvas?.renderAll();
      })
    // wait for canvas to mount first
    }, [canvas]);

However there is nothing being rendered on the canvas, I found no similar projects online and don't know the correct practice in loading SVG with react. What am I doing wrong?


Solution

  • Well, your code looks good but if you can't load svg with Fabric.js, you can confirm several things.

    1. you need to check svg file path is corrct or not.
    2. you need to check Fabric.js package version.

    I made a simple react project to show your how to load svg with Fabric.js. I provide the sample code.

    import { useEffect, useRef, useState } from 'react';
    import { fabric } from 'fabric';
    
    const FabricPanel = () => {
        // States for Canvas
        const canvasRef = useRef(null);
        const [canvas, setCanvas] = useState(null);
    
        useEffect(() => {
            if (canvasRef.current) {
                const fabricCanvas = new fabric.Canvas(canvasRef.current, {
                    fireMiddleClick: true,
                    stopContextMenu: true, 
                    selection: true,
                    preserveObjectStacking: true
                });
        
                setCanvas(fabricCanvas);
        
                fabricCanvas.backgroundColor = '#131313';
                fabricCanvas.renderAll();
    
                return () => {
                    fabricCanvas.dispose();
                };
            }
        }, []);
    
        // Load and center SVG on the canvas
        useEffect(() => {
            if (canvas) {
                fabric.loadSVGFromURL('/images/bnb.svg', (objects, options) => {
                    const svg = fabric.util.groupSVGElements(objects, options);
                    // Add the SVG to the canvas and render
                    canvas?.add(svg);
                    canvas?.renderAll();
                });
            }
        }, [canvas]);
    
        return (
            <div style={{ width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                <canvas ref={canvasRef} width="800" height="600" />
            </div>
        );
    };
    
    export default FabricPanel;
    
    

    fabric-svg-loading

    You can find this project here: Github, Stackblitz