usemap="#name" 必须与 map 的 name 属性逐字节匹配,否则热区静默失效;coords 基于 naturalWidth/naturalHeight 计算,CSS 缩放会导致偏移;SVG 用 viewBox 和百分比坐标更适配多端,poly 区域需满足最小触控尺寸。

usemap="#name" 和
热区静默失效,90% 是因为 usemap 和 name 字符串不一致。浏览器不做容错,错一个字符——比如漏掉 #、大小写混用、多一个空格——整个 area 就不响应点击,控制台也不报错。
常见错误示例:
-
usemap="mymap"(缺#) → 应为usemap="#mymap" -
usemap="#ChinaMap"对应<map name="china-map">(大小写 + 连字符不一致) -
usemap="#provinces "(末尾有空格)→ 匹配失败
建议统一用小写字母加连字符命名,例如:usemap="#china-provinces" 配合 <map name="china-provinces">;<map> 紧跟在 <img> 后面,避免被 <picture>、<figure> 或 Shadow DOM 隔离。
coords 坐标绑定 naturalWidth/naturalHeight,CSS 缩放必然偏移
这不是 bug,是规范行为:coords 永远按图片原始像素尺寸计算,和 offsetWidth、max-width、width: 100% 无关。桌面调好坐标,一上移动端或缩放视口,热区就“飘”了。
立即学习“前端免费学习笔记(深入)”;
临时补救(仅限简单场景):
- 监听
img.onload和window.resize - 算出缩放比:
scaleX = img.naturalWidth / img.offsetWidth,scaleY = img.naturalHeight / img.offsetHeight - 对每个
area.coords字符串做正则解析,按shape类型分别缩放数值:rect→ 四个数都乘对应方向缩放比;circle→ 前两个坐标乘对应缩放比,半径乘Math.min(scaleX, scaleY);poly→ 所有偶数位(x)乘scaleX,奇数位(y)乘scaleY
注意:transform: scale()、object-fit 都不能修正 coords,它们只改渲染,不触发重映射。
SVG 替代方案:viewBox + 百分比坐标天然响应式
真正需要适配多端、频繁更新热区的项目,直接用 <svg> 是目前最稳的选择。它不依赖 JS 补偿,坐标可写百分比,缩放自动重映射,还支持 aria-label、focusable="true" 和事件委托。
关键实操点:
-
<svg viewBox="0 0 [origW] [origH]" width="100%" height="auto">——viewBox必须填原始图尺寸,否则比例错乱 -
<image href="map.png" width="100%" height="100%"/>铺底图,所有热区元素(<rect>、<path>等)绝对定位其上 - 坐标换算公式:
x = (px / naturalW) * 100 + "%",y = (py / naturalH) * 100 + "%" - 别指望直接复用 PS 导出的像素坐标,得转;顶点多的
<path>在 Firefox 桌面悬停可能变慢,移动端尤其敏感
poly 区域在移动端最小尺寸必须 ≥44px
iOS Safari 对小面积 poly 响应迟钝,尤其是顶点密集、形状细长或视觉上小于 44×44px 的区域。即使开发者工具里看到元素存在、hover 样式生效,实际点击也可能被忽略、误触邻近区域,或触发延迟反馈。
规避方法:
- 用
<rect>或<circle>替代细长poly,哪怕牺牲一点精度 - 给
<path>加pointer-events: auto(默认就是,但某些 CSS 重置会覆盖) - 测试必须在真机上完成,模拟器无法复现该问题
- 若必须用
poly,确保任意两点间距离 ≥20px,且包围盒宽高均 ≥44px
复杂点不在怎么画,而在怎么让每一块热区在不同设备上都“能点中、点得准、点得稳”——这要求你从一开始就把 naturalWidth、viewBox、DPR 和最小触控尺寸全盘纳入坐标设计逻辑,而不是等上线后靠 JS 修修补补。



















