Search code examples
htmlcanvashtml5-canvas

Canvas HTML5 - Change the background color after image drawing


I search to change the background color of image after image drawing.

I have a color picker where user can change the color of image background.

this.picker.onChange = async (color) => {
    const colorPicked = color;
    this.context.fillStyle = colorPicked;
    this.context.fillRect(0, 0, 1000, 1000);
}

// ...

// The event call this function when it's ready

buildImageProcess(this.context);

// User can use the color picker to change the background color

I want change the font color after the image rendering because the image rendering is too long and user should be able to change the image color.


Solution

  • Via CSS

    If background is transparent then change the canvas CSS background-color.

    Via global composite operation

    If you want the canvas pixels set to color then use ctx.globalCompositeOperation = "destination-over" to render only on transparent and semi transparent pixels.

    If the background pixels already have a color then that is a problem.

    Via a copy of the foreground canvas

    This is the method with the least problems. in effect it creates a second layer (foreground) that you can render over a background (layer)

    Copy canvas

    To copy a canvas (foreground)

    function copyCanvas(canvas) {
        const copy = document.createElement("canvas");
        copy.width = canvas.width;
        copy.height = canvas.height;
        const ctx = copy.getContext("2d");
        ctx.drawImage(canvas, 0, 0); // render canvas to new canvas
        return copy;
    }
    

    You can also use an OffscreenCanvas or ImageBitmap though to copy the method is slightly different then above. (ALSO check browser support)

    Render layers

    Once you have a copy of the foreground pixels you can render the background then foreground for the final result

    this.picker.onChange = async (color) => {
        const ctx = this.context;
        if (this.foreGround === undefined) {  // create copy only when needed
            this.foreGround = copyCanvas(ctx.canvas);
        }
        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); // in case color is semi transparent
        ctx.fillStyle = color;
        ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
        ctx.drawImage(this.foreGround, 0, 0);
    }
    

    If you change the foreground pixels, just create a new copy of the changes. Eg in the above example just set this.foreGround = undefined before adding the background and the canvas will be copied