Home > database >  Draw a Canvas on input boxes in html
Draw a Canvas on input boxes in html

Time:01-30

I'm trying to draw a canvas line diagonally on top 2 textboxes placed diagonally (like samsung's pattern passcode) on a button click, but am unable to do so.

I tried this, but without making the input position absolute (which overlaps some text boxes), I'm not finding a good solution.

<!DOCTYPE html>
<html>
    <head>
        <style>
            * {
                z-index: 0;
            }
            canvas {
                z-index: 1;
                position: absolute;
            }
        </style>
    </head>
    <body>
    <div id="grid">
        <script>
            for(let i = 0; i < 2; i  ){
                for(let j = 0; j < 2; j  ){
                    document.getElementById("grid").innerHTML  = `<input type="text" id="cell-${i}-${j}" maxlength="1" value="${2*i j}" pattern="[A-Za-z]"/>`;
                }
                document.getElementById("grid").innerHTML  = "<br/>";
            }
        </script>
        <button onclick="draw()" id="draw_btn">Draw Line</button>
    </div>
    <script>
        function draw(){
            const canvas = document.createElement("canvas");
            canvas.width = 200;
            canvas.height = 200;

            const ctx = canvas.getContext("2d");
            ctx.strokeStyle = "#ff0000";
            ctx.lineWidth = 10;
            ctx.beginPath();
            ctx.moveTo(0,0);
            ctx.lineTo(100,100);
            ctx.stroke();
            document.body.appendChild(canvas);
        }
    </script>
    </body>
</html>

CodePudding user response:

One approach is to make the canvas absolutely positioned, and place it over the top of the text boxes.

Absolutely positioned elements are positioned relative to their nearest absolutely or relatively positioned parent. If we pop position: relative on our #grid box, and place the canvas inside, then we can position it within the bounds of the grid itself, rather than the whole document.

for(let i = 0; i < 2; i  ){
    for(let j = 0; j < 2; j  ){
        document.getElementById("grid").innerHTML  = `<input type="text" id="cell-${i}-${j}" maxlength="1" value="${2*i j}" pattern="[A-Za-z]"/>`;
    }
    document.getElementById("grid").innerHTML  = "<br/>";
}

function draw(){
    const canvas = document.createElement("canvas");
    canvas.width = 300;
    canvas.height = 40;

    const ctx = canvas.getContext("2d");
    ctx.strokeStyle = "#ff0000";
    ctx.lineWidth = 10;
    ctx.beginPath();
    ctx.moveTo(0, 0);
    ctx.lineTo(300, 40);
    ctx.stroke();
    document.getElementById("grid").appendChild(canvas);
}
#grid {
  position: relative;
}

#grid input {
  width: 150px;
  height: 20px;
  box-sizing: border-box;
}

#grid canvas {
  position: absolute;
  left: 0;
  top: 0;
  
  pointer-events: none;
}
<div id="grid"></div>
<button onclick="draw()" id="draw_btn">Draw Line</button>

I'd also recommend adding

pointer-events: none;

to the canvas, as this means the user can still interact with the input boxes below.

  • Related