area标签不支持onmouseover等事件属性,因其是void元素且事件依赖关联的img元素;需用JS监听图片mousemove并结合coords手动判断鼠标是否进入区域,或用canvas绘制热区配合isPointInPath实现精准悬停检测。

area 标签本身不支持 onmouseover 属性
直接在 <area> 标签里写 onmouseover="..." 是无效的 —— 浏览器会忽略它。这不是 bug,而是 HTML 规范明确规定的:<area> 是 void element(空元素),且其事件模型依赖于父级 <map> 与关联的 <img>(或 <object>)共同触发。鼠标事件实际发生在图片上,而非 area 区域本身。
所以真正能监听到“悬停到某个 area 区域”的方式只有一种:监听图片的 mousemove,再用 getBoundingClientRect() + area 的 coords 手动判断鼠标是否落在该区域内部。
用 JS 判断鼠标是否进入指定 area 区域
核心思路是:拿到图片 DOM 元素、遍历所有 <area>,根据 shape 类型(rect / circle / poly)解析 coords 字符串,再做几何判断。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 给
<img>加usemap并确保<map>的name匹配 - 用
document.querySelectorAll('map[name="xxx"] area')拿到所有区域 - 对每个
<area>,用element.getAttribute('coords')和element.getAttribute('shape')提取数据 -
rect:coords 是 "x1,y1,x2,y2",判断mouseX ∈ [x1,x2]且mouseY ∈ [y1,y2] -
circle:coords 是 "cx,cy,r",用距离公式(mx-cx)² + (my-cy)² ≤ r² -
poly:coords 是 "x1,y1,x2,y2,x3,y3,...",需实现点在多边形内的射线法或 winding 数算法(别手写,用isPointInPath配合临时<canvas>更稳)
推荐用 canvas 模拟热区来规避兼容性问题
原生 <area> 的坐标是相对于图片原始尺寸的,但图片常被 CSS 缩放(width/height 设置),导致 coords 失准。手动缩放计算容易出错,尤其在高 DPI 屏幕或响应式布局下。
更可靠的做法:
- 把图片用
<canvas>绘制出来(保持原始宽高) - 用
ctx.beginPath()+ctx.rect()/ctx.arc()/ctx.moveTo()+lineTo()画出各 area 对应路径 - 监听 canvas 的
mousemove,用ctx.isPointInPath(x, y)判断 - 注意:必须在每次绘制后调用
ctx.closePath(),且isPointInPath只对最后一条路径有效,所以要逐个 path 单独判断
这样完全绕开了 <area> 的 DOM 限制和缩放失真问题,逻辑清晰,调试也方便。
不要试图用 CSS :hover 伪类控制 area
<area> 不是可渲染元素,没有盒模型,因此 area:hover 在任何浏览器中都不生效。有人试过给 <area> 加 display: block 或 position: absolute,结果只是让标签在 DOM 中“存在感”变强,依然无法触发 :hover。
如果只是想实现悬停高亮效果,正确做法是:
- 用 JS 监听 mousemove,算出当前 hover 的 area 索引
- 动态修改一个覆盖层
<div>的style.left/top/width/height(对 rect)或用clip-path(对 circle/poly) - 或者直接操作 canvas,在对应区域重绘半透明色块
area 标签真正的价值在于语义化和无障碍支持(screen reader 会读出 alt),交互逻辑必须由 JS 承担 —— 这不是妥协,是它的设计定位。



















