如何在 HTML 表单输入框上叠加绘制 Canvas 对角线

本文介绍如何在不破坏布局的前提下,使用绝对定位 canvas 在多个文本框(如密码图案界面)上动态绘制对角连接线,并确保用户仍可正常操作输入框。

要在 HTML 输入框上精准绘制 Canvas 线条(例如模拟三星 Pattern Lock 的对角连线效果),关键在于将 Canvas 作为子元素嵌入到相对定位的容器中,并通过 position: absolute 进行坐标对齐,而非直接追加到

——否则线条会脱离输入框位置,且难以响应式适配。

✅ 正确实现步骤

  1. 为容器设置 position: relative
    这是绝对定位 Canvas 的“参考系”。只有当父容器具有 relative、absolute 或 fixed 定位时,其子元素的 absolute 才能相对于它定位。

  2. 将 Canvas 插入容器内部,并设为 position: absolute
    配合 left/top、width/height 及 pointer-events: none,使其视觉覆盖输入框但不影响交互。

  3. 动态计算起点与终点坐标(可选进阶)
    当前示例绘制固定对角线(从 (0,0) 到 (300,40)),实际项目中建议根据目标 元素的 getBoundingClientRect() 获取精确坐标,实现“点选连线”逻辑:

#grid {
  position: relative;
  margin: 20px 0;
}

#grid input {
  width: 150px;
  height: 40px;
  margin: 5px;
  box-sizing: border-box;
  font-size: 16px;
  text-align: center;
}

#grid canvas {
  position: absolute;
  left: 0;
  top: 0;
  pointer-events: none; /* 关键:透传鼠标事件到底层 input */
}
// 动态生成 2×2 输入框网格
const grid = document.getElementById("grid");
for (let i = 0; i < 2; i++) {
  for (let j = 0; j < 2; j++) {
    const input = document.createElement("input");
    input.type = "text";
    input.id = `cell-${i}-${j}`;
    input.maxlength = "1";
    input.value = 2 * i + j;
    input.pattern = "[A-Za-z]";
    input.style.margin = "5px";
    grid.appendChild(input);
  }
  grid.appendChild(document.createElement("br"));
}

function draw() {
  // 清除旧 canvas(避免重复叠加)
  const oldCanvas = grid.querySelector("canvas");
  if (oldCanvas) oldCanvas.remove();

  const canvas = document.createElement("canvas");
  canvas.width = 300;
  canvas.height = 80;
  const ctx = canvas.getContext("2d");

  ctx.strokeStyle = "#e74c3c";
  ctx.lineWidth = 6;
  ctx.lineCap = "round";
  ctx.beginPath();
  ctx.moveTo(10, 10);           // 起点:第一格左上附近
  ctx.lineTo(290, 70);         // 终点:最后一格右下附近
  ctx.stroke();

  grid.appendChild(canvas);
}

⚠️ 注意事项

  • 务必添加 pointer-events: none:否则 Canvas 会拦截所有点击/聚焦事件,导致输入框无法获得焦点或触发 oninput。
  • 避免内联 innerHTML += 循环:频繁修改 innerHTML 会重排重绘并丢失已绑定事件;推荐用 document.createElement + appendChild 构建 DOM。
  • Canvas 尺寸需匹配容器可视范围:若输入框有外边距或 padding,canvas.width/height 应覆盖整体区域,或通过 transform: scale() 配合 getBoundingClientRect() 精准对齐。
  • 如需多段线或路径动画:可扩展 draw() 函数,记录选中单元格顺序,再逐点绘制贝塞尔曲线或带箭头的路径。

通过以上结构化处理,你即可在任意表单网格上实现轻量、可交互、易维护的 Canvas 覆盖绘图功能——既满足 UI 层面的视觉引导需求,又不牺牲用户体验。