javascript - FabricJS v6 set Background Image - Stack Overflow

admin2025-05-01  1

The documentation of Fabric JS says they dropped support for setBackgroundObject and setBackgroundImage both of which could be set to update the canvas to have a background image:

e.g

canvas.setBackgroundImage(imageUrl, canvas.renderAll.bind(canvas), {
    backgroundImageOpacity: 0.5,
    backgroundImageStretch: false
});

//or the more convoluted:
const rect = new Rect({
  left: 0,
  top: 0,
  width: canvas.width || 0,
  height: canvas.height || 0,
  fill: "transparent",
  opacity: 0,
  stroke: "transparent",
  strokeWidth: 0,
  selectable: false,
  hasControls: false,
});
const img = new FabricImage(url, {
  crossOrigin: "anonymous",
});
img.scaleToHeight(canvas.width || 0);
img.scaleToWidth(canvas.height || 0);
rect.set("backgroundImage", img);
canvas.setBackgroundObject(rect);

How to do it in V6?

The documentation is not clear in how they expect this to be done:

rm setBackgroundColor, setBackgroundImage, setOverlayColor, setOverlayImage: assign the property directly and render the canvas

Attempts:

// Attempt A: (doesn't update the background)
const img =  FabricImage.fromURL(url, { crossOrigin: 'anonymous' });
canvas.set("backgroundImage", img);
canvas.renderAll();

//Attempt B: 
// This leads to the error below:
canvas.backgroundImage = FabricImage.fromURL(url, { crossOrigin: 'anonymous' });
canvas.renderAll();

Type 'Promise<FabricImage<Partial, SerializedImageProps, ObjectEvents>>' is missing the following properties from type 'FabricObject<Partial, SerializedObjectProps, ObjectEvents>': noScaleCache, lockMovementX, lockMovementY, lockRotation, and 223 more.ts(2740) (property) StaticCanvas.backgroundImage?: FabricObject<Partial, SerializedObjectProps, ObjectEvents> Background image of canvas instance. since 2.4.0 image caching is active, please when putting an image as background, add to the canvas property a reference to the canvas it is on. Otherwise the image cannot detect the zoom vale. As an alternative you can disable image objectCaching

The documentation of Fabric JS says they dropped support for setBackgroundObject and setBackgroundImage both of which could be set to update the canvas to have a background image:

e.g

canvas.setBackgroundImage(imageUrl, canvas.renderAll.bind(canvas), {
    backgroundImageOpacity: 0.5,
    backgroundImageStretch: false
});

//or the more convoluted:
const rect = new Rect({
  left: 0,
  top: 0,
  width: canvas.width || 0,
  height: canvas.height || 0,
  fill: "transparent",
  opacity: 0,
  stroke: "transparent",
  strokeWidth: 0,
  selectable: false,
  hasControls: false,
});
const img = new FabricImage(url, {
  crossOrigin: "anonymous",
});
img.scaleToHeight(canvas.width || 0);
img.scaleToWidth(canvas.height || 0);
rect.set("backgroundImage", img);
canvas.setBackgroundObject(rect);

How to do it in V6?

The documentation is not clear in how they expect this to be done:

rm setBackgroundColor, setBackgroundImage, setOverlayColor, setOverlayImage: assign the property directly and render the canvas

Attempts:

// Attempt A: (doesn't update the background)
const img =  FabricImage.fromURL(url, { crossOrigin: 'anonymous' });
canvas.set("backgroundImage", img);
canvas.renderAll();

//Attempt B: 
// This leads to the error below:
canvas.backgroundImage = FabricImage.fromURL(url, { crossOrigin: 'anonymous' });
canvas.renderAll();

Type 'Promise<FabricImage<Partial, SerializedImageProps, ObjectEvents>>' is missing the following properties from type 'FabricObject<Partial, SerializedObjectProps, ObjectEvents>': noScaleCache, lockMovementX, lockMovementY, lockRotation, and 223 more.ts(2740) (property) StaticCanvas.backgroundImage?: FabricObject<Partial, SerializedObjectProps, ObjectEvents> Background image of canvas instance. since 2.4.0 image caching is active, please when putting an image as background, add to the canvas property a reference to the canvas it is on. Otherwise the image cannot detect the zoom vale. As an alternative you can disable image objectCaching

Share Improve this question asked Jan 2 at 14:24 MansueliMansueli 7,0448 gold badges40 silver badges67 bronze badges 2
  • Not really, I am currently adding a rectangle with this image as background, but users can move it around still. Not great, but it kind of works (for now) for what I need. – Mansueli Commented Jan 20 at 12:05
  • I have something running, it's in an Angular Component with file upload on the screen but it should help : gist.github.com/hervehobbes/dae3b610c65772d332b1cf059d203724 – herve Commented Jan 20 at 16:17
Add a comment  | 

3 Answers 3

Reset to default 1

I have a very ugly solution. I don't like this solution and am working on trying to find a better one, but for now, this is may help you.

You can add an image as a FabricImage, which you mentioned above in the comments. The issue with this is that users can still move the image around and resize the image. To get around this, you can add the following options to your FabricImage: selectable: false, evented: false, hasControls: false, hoverCursor: "default"

Here is a react component that I have as an example

function Image({ canvas, canvasRef }) {
    const fileInputRef = useRef(null);
    const handleImageUpload = (e) => {
        const file = e.target.files[0];

        if (file) {
            const url = URL.createObjectURL(file);

            const imageElement = document.createElement("img");
            imageElement.src = url;
            imageElement.crossOrigin = "anonymous";

            imageElement.onload = () => {
                const imageWidth = imageElement.naturalWidth;
                const imageHeight = imageElement.naturalHeight;

                imageElement.width = imageWidth;
                imageElement.height = imageHeight;

                // Get canvas dimensions
                const canvasWidth = canvas.width;
                const canvasHeight = canvas.height;

                const scale = Math.min(
                    canvasWidth / imageWidth,
                    canvasHeight / imageHeight
                );

                canvas.renderAll();

                const fabricImg = new FabricImage(imageElement, {
                    left: 0,
                    top: 0,
                    scaleX: scale,
                    scaleY: scale,
                    selectable: false,
                    evented: false,
                    hasControls: false,
                    hoverCursor: "default",
                });

                canvas.add(fabricImg);
                canvas.renderAll();
            };
        }
    };

    return (
        <>
            <input
                ref={fileInputRef}
                type="file"
                accept="image/*"
                onChange={handleImageUpload}
            />
            <button onClick={handleImageUploadButtonClick}>P&ID</button>
        </>
    );
}

export default Image;

try this: const canvas = new fabric.Canvas('iCV', { backgroundImage: new fabric.Image(imageBG), })

Alternative way

working for me


Create the image first, then add it as backgroundImage

const backgroundImage = await FabricImage.fromURL(
    url, undefined, { ...options }
)

canvas.set({ backgroundImage })
转载请注明原文地址:http://www.anycun.com/QandA/1746114978a91876.html