JavaScript图片绘制矩形:onmousemove事件定位异常问题求助
图片上绘制矩形偏移问题的解决方案
问题根源
事件处理中使用的e.offsetX和e.offsetY会随事件目标变化:当鼠标移动到已显示的矩形元素上时,offsetX/Y会以矩形为参照计算,而非外层的wrapper容器,导致矩形位置计算错误。
修复方案
改用clientX/Y结合元素的绝对位置计算,确保始终获取相对于wrapper的坐标。修改后的完整代码如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <title>CSS Units px/in test</title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> </head> <body> <style> .wrapper { position:relative; } .boxOnImage { display: none; position:absolute; border:2px solid #ff6666; background-color:transparent } </style> <div id="imageMeasurement" class="wrapper"> <img id="innerImage" src="https://www.w3schools.com/html/img_chania.jpg"/> <div id="boxOnImage" class="boxOnImage"></div> </div> <script> (function () { var xs = -1; var ys = -1; var xe = -1; var ye = -1; var imageMeasurement = document.getElementById("imageMeasurement"); var box = document.getElementById("boxOnImage"); function getRelativeCoords(e) { const rect = imageMeasurement.getBoundingClientRect(); return { x: e.clientX - rect.left, y: e.clientY - rect.top }; } function isInImage(x, y) { var innerImage = document.getElementById("innerImage"); return x <= innerImage.offsetWidth && y <= innerImage.offsetHeight; } imageMeasurement.addEventListener("mousemove", function (e) { const {x, y} = getRelativeCoords(e); if (isInImage(x, y)) { if ((xe == -1 && ye == -1) && (xs != -1 && ys != -1)) { createRectangleOnImage(xs, x, ys, y); } } }); imageMeasurement.addEventListener("click", function (e) { const {x, y} = getRelativeCoords(e); if (isInImage(x, y)) { if (xs == -1 && ys == -1) { xs = x; ys = y; } else if (xe == -1 && ye == -1) { xe = x; ye = y; createRectangleOnImage(xs, xe, ys, ye); } else { xe = x; ye = y; createRectangleOnImage(xs, xe, ys, ye); } } }); document.addEventListener("keyup", function (e) { if (e.keyCode == 27) { xs = -1; ys = -1; xe = -1; ye = -1; removeRectangleOnImage(); } }); function createRectangleOnImage(xs, xe, ys, ye) { if (box.style.display != 'block') { box.style.display = 'block'; } var top = Math.min(ys, ye); var left = Math.min(xs, xe); var width = Math.abs(xe - xs); var height = Math.abs(ye - ys); box.style.top = `${top}px`; box.style.left = `${left}px`; box.style.width = `${width}px`; box.style.height = `${height}px`; } function removeRectangleOnImage() { box.style.display = "none"; } })(); </script> </body> </html>
关键改动说明
- 新增
getRelativeCoords函数:通过getBoundingClientRect()获取wrapper的视口位置,用clientX/Y减去偏移量,得到稳定的相对坐标。 - 替换所有
e.offsetX/Y的使用:统一调用getRelativeCoords获取坐标,避免事件目标变化导致的偏移。 - 简化矩形计算逻辑:用
Math.min和Math.abs替代原有的分支判断,代码更简洁易读。
内容的提问来源于stack exchange,提问作者FarHooD
相关产品推荐
相关产品推荐

