area标签本身不响应鼠标事件,无法直接触发src切换;需将事件监听绑定到img上,再通过js手动计算鼠标位置与area coords匹配来实现悬停换图。

area 标签本身不能直接触发 src 切换
很多人以为给 <area> 加 onmouseover 就能换图,但实际不行——<area> 是无内容、不可渲染的空元素,它不接收鼠标事件(除非父级 <map></map> 被正确绑定到 <img> 且浏览器支持事件透传,而绝大多数浏览器并不支持)。真正响应鼠标的其实是底层的 <img>,但它的坐标区域又无法直接映射到 JS 的 event.clientX/Y 去做热区判断。
用 usemap + JS 监听 mousemove + 区域计算来模拟
可行做法是:保留 <map></map> 和 <area> 定义热区,但把事件监听挂到图片上,再根据鼠标位置手动比对每个 <area> 的 coords 判断是否悬停。注意:coords 格式依赖 shape 属性(rect 是 x1,y1,x2,y2;circle 是 cx,cy,r;poly 是 x1,y1,x2,y2,...)。
实操建议:
- 用
getBoundingClientRect()获取图片在视口中的真实位置,避免因缩放、滚动导致坐标偏移 - 对每个
<area>提前解析coords并缓存为函数(如isInsideRect(x, y)),别每次重复解析字符串 - 别用
onmouseenter/onmouseleave——它们不适用于<area>,必须靠 JS 手动跟踪“当前悬停哪个区域” - 切换
<img>的src时,建议预加载新图(new Image().src = newSrc),否则首次悬停会卡顿
area 的 href 和 alt 与换图无关,别混淆用途
<area href="..."> 只影响点击跳转或键盘聚焦行为,对鼠标悬停无任何作用;alt 是无障碍描述,不会触发 JS 逻辑。想靠修改 alt 来驱动换图是无效的。
常见错误现象:
- 写了
onmouseover="changeImg('a.jpg')"在<area>上,但函数从不执行(控制台也无报错) - 监听了
<img>的mouseover,却误以为事件对象event.target是<area>(实际永远是<img>或文档) - 用
document.elementFromPoint()拿到的是<img>,不是<area>,因为<area>不在渲染树中
更简单可靠的替代方案:CSS background-image + hover
如果热区形状规则(比如矩形按钮),直接用绝对定位的 <div> 覆盖在图片上,配 <code>:hover 切背景图,比折腾 <map></map> 稳定得多。只有必须支持不规则多边形热区(比如地图省份)时,才值得上 JS 区域判定逻辑。
性能提示:
- 频繁调用
getBoundingClientRect()在滚动/缩放时可能触发重排,建议节流(requestAnimationFrame) - IE 11 及以下不支持
<map></map>与<img>的usemap关联在某些 SVG 场景下,需降级为 canvas 方案
真正麻烦的从来不是写几行 JS,而是处理图片缩放、高 DPI 屏幕、iframe 嵌套、以及用户关了 JS 后的降级显示——这些细节没被显式声明时,就容易在线上突然失效。











