area标签必须嵌套在map中并通过img的usemap属性绑定才能生效,无法直接响应点击事件,需监听img的click或pointerdown事件并判断target;其shape、coords等属性受限,视觉反馈能力弱,移动端存在延迟和失焦问题。

area 标签本身不能响应点击事件,必须配合 map 和 img 使用
单独写 <area> 不会显示,也不会触发任何交互——这是新手最常卡住的地方。它必须嵌套在 <map></map> 元素里,并通过 img 的 usemap 属性绑定。浏览器只把 area 当作图像上的“热区”,不渲染为独立 DOM 节点,所以 addEventListener('click') 直接绑在 area 上无效。
正确结构是:
@@##@@ <map name="seatmap"><area shape="rect" coords="10,20,60,70" data-seat-id="A1" alt="A1座"> <area shape="circle" coords="150,100,25" data-seat-id="B3" alt="B3座"></map>
-
shape值只能是rect、circle、poly或default,不能用roundrect等自定义值 -
coords是像素坐标,必须严格对应底图尺寸;若图片缩放(比如用 CSS 设置width:100%),热区会错位 -
alt必须提供,否则可访问性失败,部分屏幕阅读器会跳过该区域
用 JavaScript 捕获 area 点击,要监听 img 而非 area
因为 area 不是普通可交互元素,事件委托必须落在 img 上,并通过 event.target 判断是否命中了某个 area。
示例代码:
const img = document.querySelector('img[usemap]');
img.addEventListener('click', (e) => {
if (e.target.tagName === 'AREA') {
const seatId = e.target.dataset.seatId;
console.log('选中座位:', seatId);
// 这里触发选座逻辑,比如高亮、加入订单等
}
});
- 不要用
document.addEventListener('click', ...)全局监听,容易误触其他元素 - 如果底图是 SVG,直接用
<rect></rect>/<circle></circle>更可控,area仅适用于无法改用 SVG 的旧图资源 -
e.target在某些老版本 Safari 中可能为null,建议加空值判断
动态更新座位状态时,area 无法直接设置 class 或 style
area 是 void 元素,没有子内容,也不能被 CSS 伪类(如 :hover)可靠控制样式——你不能给它加背景色或边框。想体现“已售/已选/禁用”状态,必须换思路。
- 方案一:用 JS 动态切换底图(如
seat-plan-occupied.png),再重置img.src - 方案二:在
img后面叠加一层透明canvas,按需绘制座位状态(适合复杂高亮逻辑) - 方案三:放弃
area,改用绝对定位的div覆盖在图片上,每个div对应一个座位(更灵活,但需手动计算坐标)
如果坚持用 area,唯一能做的视觉反馈只有 title 属性(鼠标悬停提示)和 alt(无障碍支持),别指望它能变色或闪烁。
移动端点击 area 容易失焦,必须处理 touch 事件和延迟
在 iOS Safari 和部分安卓浏览器中,area 的 click 事件有约 300ms 延迟,且手指稍有移动就判定为滑动而非点击,导致选座失败。
- 务必同时监听
touchstart并e.preventDefault(),避免滚动干扰 - 推荐用
pointerdown替代click,兼容性好且无延迟(IE11+ / Chrome 55+ / Safari 13+) - 不要依赖
area的href属性跳转——它会触发页面刷新,破坏选座流程
真正难的不是画热区,而是让几百个座位在不同设备、不同缩放、不同网络条件下都稳定响应。一旦用户反馈“点不中”,八成是坐标没对齐或事件没兜住。

前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











