You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用JavaScript在图片上绘制可写入内容的矩形区域

原生JS实现图片上可写入内容的交互矩形绘制

核心实现采用三层叠加结构,无需引入第三方库,兼容桌面端和移动端场景:

  • 最底层:展示习题原图
  • 中间层:透明Canvas层,捕获鼠标/触摸事件,实时绘制矩形选框边框
  • 最上层:选框绘制完成后,在对应坐标挂载可编辑输入组件,支持内容写入、编辑、删除

具体实现步骤

1. 搭建基础HTML结构

外层容器设置相对定位,所有内部元素基于容器做位置校准,避免缩放、偏移导致的选框错位:

<div class="worksheet-wrap" style="position: relative; display: inline-block; line-height: 0;">
  <img id="sheetImg" alt="习题图片" src="your-target-image.jpg">
  <canvas id="drawLayer" style="position: absolute; top:0; left:0; cursor: crosshair;"></canvas>
  <div id="inputLayer" style="position: absolute; top:0; left:0; width: 100%; height: 100%;"></div>
</div>

2. 初始化尺寸校准

等图片加载完成后,将Canvas层尺寸和图片实际渲染尺寸完全对齐,统一绘制样式:

const img = document.getElementById('sheetImg');
const canvas = document.getElementById('drawLayer');
const ctx = canvas.getContext('2d');
const inputLayer = document.getElementById('inputLayer');

let isDrawing = false;
let drawStart = {x:0, y:0};
// 存储所有已创建的答题区域数据,可直接序列化存储
const answerAreaList = [];

img.onload = () => {
  canvas.width = img.offsetWidth;
  canvas.height = img.offsetHeight;
  ctx.strokeStyle = '#165DFF';
  ctx.lineWidth = 2;
}

3. 实现拖拽绘制矩形逻辑

监听鼠标事件,拖拽过程中实时预览矩形效果,拖拽结束后校验选框有效性:

// 鼠标按下:记录绘制起点
canvas.addEventListener('mousedown', (e) => {
  isDrawing = true;
  const canvasRect = canvas.getBoundingClientRect();
  drawStart.x = e.clientX - canvasRect.left;
  drawStart.y = e.clientY - canvasRect.top;
})

// 鼠标移动:实时绘制临时矩形预览
canvas.addEventListener('mousemove', (e) => {
  if (!isDrawing) return;
  const canvasRect = canvas.getBoundingClientRect();
  const currentX = e.clientX - canvasRect.left;
  const currentY = e.clientY - canvasRect.top;

  // 清空画布重绘,避免预览残影
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  redrawSavedAreas();
  // 绘制当前拖拽的临时选框
  ctx.strokeRect(
    drawStart.x, 
    drawStart.y, 
    currentX - drawStart.x, 
    currentY - drawStart.y
  );
})

// 鼠标抬起:完成绘制,生成可编辑区域
canvas.addEventListener('mouseup', (e) => {
  if (!isDrawing) return;
  isDrawing = false;
  const canvasRect = canvas.getBoundingClientRect();
  const endX = e.clientX - canvasRect.left;
  const endY = e.clientY - canvasRect.top;

  // 计算选框真实坐标和尺寸,兼容反向拖拽(从右下往左上选的场景)
  const area = {
    x: Math.min(drawStart.x, endX),
    y: Math.min(drawStart.y, endY),
    w: Math.abs(endX - drawStart.x),
    h: Math.abs(endY - drawStart.y),
    content: ''
  }

  // 过滤尺寸过小的误触选框
  if (area.w < 20 || area.h < 20) {
    ctx.clearRect(0,0,canvas.width, canvas.height);
    redrawSavedAreas();
    return;
  }

  answerAreaList.push(area);
  mountInputArea(area);
})

// 重绘所有已保存的选框边框
function redrawSavedAreas() {
  answerAreaList.forEach(item => {
    ctx.strokeRect(item.x, item.y, item.w, item.h);
  })
}

4. 绑定选框内容写入能力

选框绘制完成后,在对应坐标挂载和选框尺寸完全匹配的多行输入框,支持内容编辑、删除:

function mountInputArea(area) {
  const textarea = document.createElement('textarea');
  // 输入框样式和选框完全对齐
  textarea.style.cssText = `
    position: absolute;
    left: ${area.x}px;
    top: ${area.y}px;
    width: ${area.w}px;
    height: ${area.h}px;
    border: none;
    background: rgba(22, 93, 255, 0.08);
    padding: 4px 6px;
    font-size: 15px;
    resize: none;
    outline: none;
    line-height: 1.4;
  `;

  // 实时同步输入内容到存储数据
  textarea.addEventListener('input', () => {
    area.content = textarea.value;
  })

  // 右键点击选框可删除
  textarea.addEventListener('contextmenu', (e) => {
    e.preventDefault();
    textarea.remove();
    const idx = answerAreaList.indexOf(area);
    if (idx > -1) answerAreaList.splice(idx, 1);
    ctx.clearRect(0,0,canvas.width, canvas.height);
    redrawSavedAreas();
  })

  inputLayer.appendChild(textarea);
  textarea.focus();
}

扩展适配说明

  • 移动端适配:将上述鼠标事件替换为对应touchstart/touchmove/touchend事件,坐标计算时取e.touches[0]的触点坐标即可
  • 学生端下发:下发习题时可关闭Canvas绘制权限,清空所有输入框内容,只保留选框边框即可
  • 选框调整能力:如果需要支持已绘制选框的拖拽移动、尺寸调整,可给每个选框增加8个控制点,监听拖拽事件更新坐标和输入框位置即可
  • 数据存储:所有选框的坐标、尺寸、填写内容都存在answerAreaList数组中,可直接序列化为JSON存入后端,下次加载时自动重绘选框、回填内容即可

内容的提问来源于stack exchange,提问作者Mahmoud Ramadan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 21:03:18