qr-code-styling
qr-code-styling copied to clipboard
Size of qrcode is not fixed when data string is different
I also ran into this issue.
+1
+1
Do you mean the size of the qrcode? I was having trouble with this last night and the only thing I could figure out that didn't mess with the size when I had too much data was changing errorCorrectionLevel to 'M'
@ezodnem It seems that this library has been orphaned and there is no one to take care of it anymore. :'(
Hi, this behavior I believe is expected. Please see below why.
Lets say you have a 300x300 pixel canvas to show the QR-code in. Each "dot" in the qr-code takes up a certain amount of space (with this library you can let some dots render as lines as well but the concept still applies). Lets say 15x15 pixels including margins between the dots. This means you have a grid of 300/15 = 20x20 dots. Within that grid your data is represented.
Now you increase the amount of data. At some point you will need a bigger grid to represent all the data since 20x20 is not big enough anymore. So the library goes to the next grid which has enough space: 21x21. This means your dots would need to be 300/21 ≈ 14,29 -> 14,29x14,29 pixels to nicely fill the 300x300 canvas. This is an issue because if you want your qr-code to be a sharp image you must avoid rendering lines "between" pixels
So instead "dots" become 14x14 pixels. The width and height now becomes: 14x21 = 294 pixels This leaves a margin around the image of (300-294)/2 = 3 pixels. This is the change in size.
@ezodnem changing the errorCorrectionLevel to "M" in your case probably made the required grid more suitable for your data range, meaning for all the different data inputs you provided the same grid could be used to represent the data.
This "issue" of changing the grid size and thus the dimensions of the qr-code should become less and less the more data you have since the ever increasing grid will be able to represent more data without needing to go to a bigger grid. But I am not sure of this though...
Maybe there is an option to force "dots" not to be whole integers and render a more blurry qr-code that fully respects the set size of the canvas. Though I don't think this would be preferable in any situation..
Hopefully this helps somewhat in understanding the cause.
This is what I use to make sure that the QR code has consistent sizing, regardless of the data string:
- Generate the QR code as SVG
- Get the SVG content and remove the 2nd node. This is the one causing all the trouble!
- Use
SVGGraphicsElement.getBBox
to fit the canvas of the SVG to the QR code content. Now you have an SVG string without any white space / margins, and you can adjust it to any size you want.
async function removeWhiteSpaceFromQrCodeSvg(svgString: string): Promise<string> {
const element = document.createElement("div");
element.innerHTML = svgString;
const svgElement = element.getElementsByTagName("svg")[0] as SVGGraphicsElement;
// The second child from the generated SVG adds useless white space around the QR code.
// We remove the child element to make sure that the SVG does not contain any white space.
svgElement.removeChild(svgElement.childNodes[1]);
// We need to temporarily insert the SVG element into the DOM in order to get the correct bounding box dimensions.
const elementToRemove = document.body.insertAdjacentElement("beforeend", svgElement);
const bbox = svgElement.getBBox();
const viewBox = [bbox.x, bbox.y, bbox.width, bbox.height].join(" ");
svgElement.setAttribute("viewBox", viewBox);
elementToRemove!.remove();
return svgElement.outerHTML;
}