如何使用JavaScript在图片上交互式绘制矩形边界框并读取坐标?
原生JavaScript矩形标注库推荐
1. Fabric.js
- 特点:功能全面的Canvas图形库,纯原生JS即可使用,无需任何框架依赖。支持在图片上绘制、拖拽、调整大小、删除矩形框,能轻松获取每个矩形的坐标(x、y、宽度、高度),还支持其他图形的绘制与编辑,扩展性强。
- 快速上手示例:
// 初始化Fabric画布 const canvas = new fabric.Canvas('canvas'); // 加载背景图片 fabric.Image.fromURL('your-image.jpg', function(img) { canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas)); canvas.setWidth(img.width); canvas.setHeight(img.height); }); // 实现矩形绘制逻辑 let isDrawing = false; let currentRect; canvas.on('mouse:down', function(o) { isDrawing = true; const pointer = canvas.getPointer(o.e); currentRect = new fabric.Rect({ left: pointer.x, top: pointer.y, width: 0, height: 0, fill: 'rgba(0,255,0,0.3)', stroke: 'green', strokeWidth: 2 }); canvas.add(currentRect); }); canvas.on('mouse:move', function(o) { if (!isDrawing) return; const pointer = canvas.getPointer(o.e); const width = pointer.x - currentRect.left; const height = pointer.y - currentRect.top; currentRect.set({ width: Math.abs(width), height: Math.abs(height) }); if (width < 0) currentRect.set({ left: pointer.x }); if (height < 0) currentRect.set({ top: pointer.y }); canvas.renderAll(); }); canvas.on('mouse:up', function() { isDrawing = false; // 获取当前矩形的坐标信息 console.log('矩形坐标:', { x: currentRect.left, y: currentRect.top, width: currentRect.width, height: currentRect.height }); }); - 优势:文档完善,社区活跃,后续如果需要扩展标注功能(比如添加文字、其他形状)会很方便。
2. Konva.js
- 特点:轻量级2D Canvas交互库,原生JS兼容,专注于图形交互体验。支持矩形的创建、拖拽、缩放,内置完善的事件系统,处理交互逻辑更简洁直观。
- 快速上手示例:
// 创建舞台与图层 const stage = new Konva.Stage({ container: 'container', width: 800, height: 600 }); const layer = new Konva.Layer(); stage.add(layer); // 加载图片 const imageObj = new Image(); imageObj.onload = function() { const image = new Konva.Image({ x: 0, y: 0, image: imageObj, width: stage.width(), height: stage.height() }); layer.add(image); layer.draw(); }; imageObj.src = 'your-image.jpg'; // 矩形绘制逻辑 let isDrawing = false; let startX, startY; let currentRect; stage.on('mousedown', function(e) { isDrawing = true; const pos = stage.getPointerPosition(); startX = pos.x; startY = pos.y; currentRect = new Konva.Rect({ x: startX, y: startY, width: 0, height: 0, fill: 'rgba(255,0,0,0.3)', stroke: 'red', strokeWidth: 2 }); layer.add(currentRect); }); stage.on('mousemove', function(e) { if (!isDrawing) return; const pos = stage.getPointerPosition(); const width = pos.x - startX; const height = pos.y - startY; currentRect.width(Math.abs(width)); currentRect.height(Math.abs(height)); if (width < 0) currentRect.x(pos.x); if (height < 0) currentRect.y(pos.y); layer.draw(); }); stage.on('mouseup', function() { isDrawing = false; // 获取当前矩形的坐标信息 console.log('矩形坐标:', { x: currentRect.x(), y: currentRect.y(), width: currentRect.width(), height: currentRect.height() }); }); - 优势:API简洁,性能优秀,交互流畅,适合对标注体验要求较高的场景。
3. 零依赖备选:原生Canvas自定义实现
如果不想引入第三方库,也可以直接用原生Canvas API实现,代码量不大且完全可控:
const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const img = new Image(); img.src = 'your-image.jpg'; // 存储所有绘制的矩形 const rects = []; let isDrawing = false; let currentRect = { x: 0, y: 0, width: 0, height: 0 }; img.onload = function() { canvas.width = img.width; canvas.height = img.height; ctx.drawImage(img, 0, 0); }; // 鼠标按下开始绘制 canvas.addEventListener('mousedown', (e) => { isDrawing = true; const canvasRect = canvas.getBoundingClientRect(); currentRect.x = e.clientX - canvasRect.left; currentRect.y = e.clientY - canvasRect.top; }); // 鼠标移动更新矩形 canvas.addEventListener('mousemove', (e) => { if (!isDrawing) return; const canvasRect = canvas.getBoundingClientRect(); currentRect.width = e.clientX - canvasRect.left - currentRect.x; currentRect.height = e.clientY - canvasRect.top - currentRect.y; // 重绘图片与已有矩形 ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(img, 0, 0); rects.forEach(drawRect); drawRect(currentRect); }); // 鼠标结束绘制 canvas.addEventListener('mouseup', () => { isDrawing = false; rects.push({ ...currentRect }); console.log('所有矩形坐标:', rects); }); // 绘制矩形的工具函数 function drawRect(rect) { ctx.fillStyle = 'rgba(0,0,255,0.3)'; ctx.strokeStyle = 'blue'; ctx.lineWidth = 2; ctx.fillRect(rect.x, rect.y, rect.width, rect.height); ctx.strokeRect(rect.x, rect.y, rect.width, rect.height); }
- 优势:零外部依赖,代码完全自定义,适合需求简单、希望最小化项目体积的场景。
内容的提问来源于stack exchange,提问作者jxw
相关产品推荐
相关产品推荐

