coords值必须基于img.naturalWidth/naturalHeight计算,与CSS渲染尺寸无关;rect需x1<y1<x2<y2四整数,circle需cx,cy,r且r为正整数,poly坐标须成对偶数;area须嵌入正确name的map且img usemap属性#和大小写严格匹配。

原始坐标必须按 img.naturalWidth 和 img.naturalHeight 读取,硬写 CSS 渲染尺寸下的值一定会点不中——这不是 JS 没跑,是浏览器根本没拿你写的坐标去比对。
coords 值为什么只认 naturalWidth/naturalHeight
HTML 规范强制 coords 解析单位为原始图像像素,与 CSS width/height、max-width 或容器限制完全无关。哪怕图片被缩放到 50×30px 显示,coords="100,200,300,400" 仍按原图 1200×800 下的 100px、200px 等位置匹配,超出显示区域就静默失效。
- 用
offsetWidth/offsetHeight取渲染尺寸再填 coords → 必错 - 用设计稿标注的“距左 20px、宽 120px”直接套成
coords="20,0,120,80"→ 错把宽高当右下角 - 在 Figma 里量坐标时以画布左上为原点,而非图片自身左上角(0,0) → 偏移固定值
rect/circle/poly 的 coords 格式差异和校验要点
不同 shape 对 coords 的解析规则完全不同,填错结构或数值范围会导致热区收缩为点、偏移出界,甚至整块区域被忽略(浏览器不报错)。
-
shape="rect":必须且仅能是x1,y1,x2,y2四个整数,且严格满足x1 < x2且y1 < y2;填成"100,50,80,150"(x2 ≤ x1)→ 区域无效 -
shape="circle":格式为cx,cy,r,r必须为正整数;r=0或小数(如"100,80,29.5")→ Safari 静默跳过 -
shape="poly":坐标成对出现,总数必须为偶数;导出带空格/换行(如"60,40, 120,30")→ Chrome 可能容忍,Safari 直接截断
动态重算 coords 的最小可靠代码模板
不能只靠 window.resize,必须监听 img.onload 确保 naturalWidth 可读;缩放比要分 scaleX 和 scaleY 独立计算,尤其图片被拉伸时。
立即学习“前端免费学习笔记(深入)”;
const img = document.querySelector('img');
const map = document.querySelector('map');
const areas = map.querySelectorAll('area');
<p>const updateCoords = () => {
if (!img.naturalWidth) return;
const scaleX = img.offsetWidth / img.naturalWidth;
const scaleY = img.offsetHeight / img.naturalHeight;</p><p>areas.forEach(area => {
const [x1, y1, x2, y2] = area.coords.split(',').map(Number);</p><pre class='brush:php;toolbar:false;'>if (area.shape === 'rect') {
area.coords = [
Math.round(x1 * scaleX),
Math.round(y1 * scaleY),
Math.round(x2 * scaleX),
Math.round(y2 * scaleY)
].join(',');
}
// circle/poly 同理,需分别处理半径或逐对缩放}); };
img.addEventListener('load', updateCoords); // ResizeObserver 比 window.resize 更稳,尤其在 flex/grid 容器中 new ResizeObserver(updateCoords).observe(img);
真正容易被忽略的是:area 必须嵌在 <map name="xxx"> 内,且 <img usemap="#xxx"> 的 # 不能漏、大小写不能错——错一个字符,所有 coords 再准也没用。



















