和需用js按渲染尺寸与原始尺寸缩放比动态重算coords,因coords基于img.naturalwidth/height的绝对像素,不随css缩放自适应;须分别计算scalex、scaley,按shape类型逐坐标缩放并setattribute更新。

HTML 的 <map></map> 和 <area> 本身没有响应式能力,直接写死的 coords 在缩放或不同分辨率下必然错位。必须用 JS 动态重算坐标,核心是「按实际渲染尺寸与原始尺寸的缩放比」做线性映射。
为什么 coords 不随 CSS 缩放自动适配?
<area> 的 coords 值是绝对像素坐标,绑定的是图片原始尺寸(img.naturalWidth/img.naturalHeight),和 img.offsetWidth/img.offsetHeight 无关。哪怕你用 width: 100% 或 transform: scale() 拉伸图片,<area> 还是照着原始图左上角原点在算——点就偏了。
常见错误现象:
- 图片用
max-width: 100%响应式后,热点区域只在小屏下半部分可点 - 大屏全屏展示时,鼠标悬停提示总出现在图片右侧空白处
- 用开发者工具临时加
border: 1px solid red到<img>,发现<area>区域完全不贴合渲染后的图像轮廓
如何正确计算 coords 缩放比?
关键不是“屏幕宽度”,而是这张图在当前页面里实际渲染出来的宽高,和它原始宽高的比值。必须分两步取值:
- 记录原始尺寸:
const naturalW = img.naturalWidth;、const naturalH = img.naturalHeight; - 获取渲染尺寸:
const renderedW = img.offsetWidth;、const renderedH = img.offsetHeight; - 算出两个独立缩放因子:
const scaleX = renderedW / naturalW;、const scaleY = renderedH / naturalH;
注意:不能只用一个缩放比(比如 renderedW / 1920)——因为图片可能被拉伸变形,或设置了 object-fit: contain,此时宽高缩放比不一致,必须分别处理。
怎么批量更新所有 的 coords?
遍历 img.map?.areas,按 shape 类型分别处理每组 coords 字符串:
- 矩形(
rect):4 个值,顺序是x1,y1,x2,y2,全部乘对应缩放比:[x1*scaleX, y1*scaleY, x2*scaleX, y2*scaleY] - 圆形(
circle):3 个值,cx,cy,r,前两个乘各自缩放比,半径也需缩放:[cx*scaleX, cy*scaleY, r*scaleX](半径用scaleX更稳妥,避免椭圆) - 多边形(
poly):偶数个值,两两为x,y对,逐对应用缩放:[x0*scaleX, y0*scaleY, x1*scaleX, y1*scaleY, ...]
实操建议:
- 把原始坐标导出时,务必确认工具(如 image-map.net)输出的是基于原始图尺寸的值,不是缩放预览图上的坐标
- 更新
coords后,立即调用area.setAttribute('coords', newCoords.join(',')),不要直接改area.coords属性(部分浏览器不触发重绘) - 监听两个时机:图片加载完成(
img.onload)和窗口大小变化(window.addEventListener('resize', handler))
容易被忽略的边界情况
缩放比计算依赖图片已加载完成且尺寸可读。如果图片是懒加载、或通过 CSS 设置了 aspect-ratio、或父容器用了 flex / grid 导致渲染尺寸延迟稳定,offsetWidth 可能拿不到真实值。最稳的方式是:在 img.onload 后加一层 requestAnimationFrame 再取尺寸,确保 layout 已完成。另外,img.naturalWidth 在 CORS 图片上可能为 0,需提前检查并 fallback 到预设尺寸。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











