Search code examples
javascriptreactjscanvasqr-code

Remove black background on canvas in react js


I am displaying the qr-code on the screen using the qrcode.react library in react. It displays correctly on the srceen with white backgroung and I can scan it as well.

The Qr code renderer code:

{qrCodeDataUrl && (
    <QRCodeCanvas
      value={qrCodeDataUrl}
      size={350}
      className="qr-code"
      imageSettings={{
        src: "/media/logos/favicon.ico",
        height: 64,
        width: 128,
        excavate: true,
      }}
      level="H"
    />
)}

I also have a download button where users can download that QR code. but when it is downloaded, the background is transparent (black). so that I cannot scan it. How to make the background white?

I have tried some solutions, like setting the bgColor property on the QRCodeCanvas element to white and styling the qrcode component as well in the div but it is not working.

The download function:

  const downloadQRCode = (url: string) => {
    const canvas = document.querySelector(".qr-code") as HTMLCanvasElement;
    const dataUrl = canvas.toDataURL("image/jpeg");
    const downloadLink = document.createElement("a");
    downloadLink.href = dataUrl;
    downloadLink.download = "qr-code.png";
    document.body.appendChild(downloadLink);
    downloadLink.click();
    document.body.removeChild(downloadLink);
  };

Solution

  • The default color of a canvas is transparent, and it seems that your background is black, so you need to give the canvas you are creating a white background color.

    For example:

     const downloadQRCode = (url: string) => {
        var canvas = document.querySelector(".qr-code") as HTMLCanvasElement;
        var image = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
    
        // Create a new off-screen canvas with the same dimensions as the original canvas
        const offscreenCanvas = document.createElement('canvas');
        offscreenCanvas.width = 200;
        offscreenCanvas.height = 200;
        
        // Get the context of the off-screen canvas
        const offscreenContext = offscreenCanvas.getContext('2d');
        
        // Set the background color of the off-screen canvas
        offscreenContext.fillStyle = '#fff';
        offscreenContext.fillRect(0, 0, 200, 200);
    
        // Draw the original canvas onto the off-screen canvas
        offscreenContext.drawImage(image, 30, 30);
        
        const dataUrl = offscreenCanvas.toDataURL("image/jpeg"); 
        const downloadLink = document.createElement("a");
        downloadLink.href = dataUrl;
        downloadLink.download = "qr-code.png";
        document.body.appendChild(downloadLink);
        downloadLink.click();
        document.body.removeChild(downloadLink);
      };
    

    Update: The correct and simple way is simply to add includeMargin.

    {qrCodeDataUrl && (
        <QRCodeCanvas
          value={qrCodeDataUrl}
          size={350}
          className="qr-code"
          imageSettings={{
            src: "/media/logos/favicon.ico",
            height: 64,
            width: 128,
            excavate: true,
          }}
          level="H"
          includeMargin={true}
        />
    )}