简体   繁体   中英

Canvas borders between rectangles

I have made a QR-code generator.

It takes a string of spaces and '#' to generate an image using the canvas. This string is given to the following function as the text parameter:

export const drawQR = (text) => {
    // Set up canvas and go to top left
    let canvas = document.getElementById("qr-code-canvas");
    let ctx = canvas.getContext("2d");
    ctx.lineWidth = "1";
    // ctx.moveTo(0,0)

    // calculate box height and width
    let lines = text.split('\n');
    let boxes_h = lines.length;
    let chars_first = Array.from(lines[0]);
    let boxes_w = chars_first.length;
    let width = canvas.clientWidth
    let height = canvas.clientHeight;

    let box_height = height/boxes_h;
    let box_width = width/boxes_w;

    // Keep track of current position
    let x = 0;
    let y = 0;

    lines.forEach((line) => {
        Array.from(line).forEach((char) => {
            if (char == " ") {
                ctx.beginPath();
                ctx.fillStyle = "white";
                ctx.rect(x, y, box_width, box_height);
                ctx.fill();
            } else if (char == "#") {
                ctx.beginPath();
                ctx.fillStyle = "black";
                ctx.rect(x, y, box_width, box_height);
                ctx.fill();
            } else {
                console.error(`error: unkown character in QR code: ${char}`)
            }
            x += box_width;
        });
        x = 0;
        y += box_height;
    });
}

Now I just draw a white rectangle for each space in the string and a black one for each '#' in the string. A new line goes down one box and starts back at the left again.

The problem I have with this is that there are small borders between the boxes: 二维码1

I have tried making the boxes bigger:

ctx.rext(x, y, box_width + 1, box_height + 1);

This works pretty well for bigger boxes, but when the boxes get smaller, I start to get artifacts (zoom in on the top left box for example):

二维码 2

Drawing a border for each rectangle has a similar result.

Does anyone know how to fix these issues?

Thank you in advance for your answers, Jonas

I had a very similar problem. I have solved it by having the box_width and the box_height of the rectangles as integers:

let box_height = Math.floor(height/boxes_h);
let box_width = Math.floor(width/boxes_w);

This happens because HTML5 canvas supports sub-pixel rendering, and it will try to use anti-aliasing to smooth the lines. More info here:

https://web.dev/canvas-performance/#avoid-floating-point-coordinates

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM