最可靠方式是用mouseenter/mouseleave绑定到元素边界,避免mouseover/mouseout在子元素间切换时误触发;需用addEventListener添加监听器;area标签不支持事件,应绑定到img并手动坐标比对;移动端需用pointerenter/pointerleave或touchstart;主动判断需结合mousemove与getBoundingClientRect实时校验鼠标是否在区域内。

用 mouseenter 和 mouseleave 判断是否进入映射区域
直接绑定 mouseenter 和 mouseleave 是最简单、最可靠的方式。它们按元素**边界**触发,不因内部子元素切换而误判,天然适合“映射区域”这类需要精确进出感知的场景。
常见错误现象:用 mouseover/mouseout 导致鼠标在区域内部从文字移到图标时反复触发“离开”,hover 状态闪烁、动画跳变。
- 必须用
addEventListener,避免element.onmouseenter = handler覆盖前一个监听器 - 如果映射区域是
<map>+<area>,注意:<area>不支持事件监听,得把事件挂到包裹它的<img>上,再结合event.offsetX/Y或getBoundingClientRect()手动比对坐标 - 移动端默认不触发这两个事件,需搭配
pointerenter/pointerleave或 fallback 到touchstart
用 getBoundingClientRect() 实时检测鼠标坐标是否在区域内
当需要“不依赖事件触发”的主动判断(比如拖拽中持续校验、Canvas 覆盖层避让),就得靠坐标计算。核心是:拿到鼠标位置,再和目标区域的矩形边界比对。
关键操作:
立即学习“前端免费学习笔记(深入)”;
- 监听
mousemove时,用e.clientX和e.clientY获取视口坐标(不是pageX/pageY,滚动时会偏移) - 调用目标元素的
getBoundingClientRect(),得到{left, top, right, bottom} - 判断:
clientX >= rect.left && clientX = rect.top && clientY
容易踩的坑:
- 如果区域有
transform: scale()或rotate(),getBoundingClientRect()返回的是渲染后尺寸,但坐标仍可用;若需逻辑像素级精度(如 Canvas 绘图),要除以window.devicePixelRatio - 区域被
overflow: hidden裁剪时,getBoundingClientRect()返回完整框,得额外检查element.scrollLeft和scrollTop是否覆盖了鼠标点
<area> 映射区域必须手动做坐标映射
<area> 标签本身不能监听事件,所谓“鼠标进入映射区域”,本质是判断鼠标是否落在 <img> 上某个预设坐标范围内。这需要你把 coords 属性解析成可比对的几何形状。
例如一个矩形 <area shape="rect" coords="10,20,100,80">,对应区域就是左上(10,20)、右下(100,80)的矩形。但注意:
- 这些坐标是相对于图片原始尺寸的,而
img在页面中可能被 CSS 缩放或拉伸——必须用img.naturalWidth/Height和img.clientWidth/clientHeight算出缩放比例,再将鼠标坐标反向映射回去 - 圆形(
circle)和多边形(poly)需用数学公式判断点是否在内,不能只靠矩形包围盒 - 别用
offsetLeft/offsetTop计算图片位置,它受父级position影响;必须用getBoundingClientRect()
真正容易被忽略的是绝对定位子元素溢出
即使用了 mouseenter,如果映射区域内部有 position: absolute 的子元素超出了父容器边界,鼠标划过那个溢出部分时,mouseenter 仍不会触发——因为事件只响应在父元素“布局边界”内,不包含视觉溢出区。
此时只能退回到坐标检测法,并把所有相关子元素的 getBoundingClientRect() 合并为一个联合区域(union rect),或者改用 elementFromPoint(x, y) 反查 DOM 节点是否属于该映射区域的后代。



















