最轻量静态热区用+(IE9+兼容),但仅适固定图与静态坐标;动态需求须用Leaflet/高德/百度等地图库或Canvas自绘。

不依赖地图 SDK 就能做静态热区,用 <map></map> + @#@#@#@#@#@#@#@#@#@0)点选顶点导出坐标,别手算;UI 给的标注图务必确认是“按原始尺寸截图”
<li>每个 <code><area> 只能绑定一个 href 或用 JS 监听 click,想做 hover 效果得靠 CSS + title 或额外加一层透明 canvas 覆盖
Leaflet 动态绘制多边形(无地图 SDK 也能跑)
Leaflet 不强制联网加载底图,纯前端即可完成坐标录入、拖拽编辑、点面判断。适合内部系统、离线场景或仅需几何逻辑的业务。
- 初始化时传空
center和极小zoom,或用L.map(...).setView(...)后立刻map.removeLayer(map._layers[...])清掉瓦片层,只留矢量层 - 用
L.polygon([[lat1,lng1], [lat2,lng2], ...])创建,.addTo(map)即显;启用编辑:polygon.editing.enable() - 获取顶点:
polygon.getLatLngs()返回L.LatLng[],转数组用.map(ll => [ll.lat, ll.lng]) - 判断点是否在内:
L.Polygon.prototype.contains不暴露,得自己调leaflet-pip插件,或用更轻的point-in-polygon库(传 [[x,y],...] 和 [x,y] 即可)
高德/百度/腾讯地图 API 的坑点直说
这些 SDK 看似封装好,但实际集成时卡住的往往不是“怎么画”,而是权限、坐标系、生命周期和事件时机。
- 高德
AMap.Driving或DrawingManager默认用 GCJ-02 坐标,若你后端存的是 WGS84(GPS 原始坐标),直接画出来会偏移几百米 —— 必须用AMap.convertFrom(..., 'gps')转 - 百度地图的
DrawingManager在overlaycomplete回调里拿e.overlay.getPath(),返回的是BMap.Point[],要转成数组得.map(p => [p.lat, p.lng]),注意顺序是lat,lng(反直觉) - 腾讯地图
qq.maps.Polygon的path参数接受qq.maps.LatLng[],但qq.maps.LatLng构造函数是new qq.maps.LatLng(lat, lng),参数顺序又是lat,lng—— 和 Leaflet 的[lat,lng]一致,但和 GeoJSON 的[lng,lat]相反 - 所有地图库在
map.on('load', ...)之前绑定绘制工具,大概率失效;高德必须等map.getZoom() > 0才能添加图层
Canvas 手动画多边形(完全自控,但无地理语义)
如果只是 UI 上示意“一块区域”,不需要经纬度、不对接 GIS 数据,<canvas></canvas> 是最自由的选择:坐标任意定、样式随心改、性能扛得住上千个区域。
- 用
ctx.beginPath()→ctx.moveTo(x,y)→ 多个ctx.lineTo(x,y)→ctx.closePath()→ctx.fill() - 监听
canvas的mousemove+isPointInPath()实现 hover 高亮,但注意:该方法只对**当前路径**有效,每次绘制新图形前要ctx.beginPath(),否则所有区域混在一起判断 - 保存坐标用数组推入
{x, y}对象,后续要做缩放适配,就得把所有x,y乘上缩放比;想支持拖拽,就得自己实现 hit-test 和 translate 逻辑 - 没有内置的“点是否在多边形内”API,得引入
robust-point-in-polygon或手写射线法 —— 别信网上抄来的简版,边界点、共线、凹多边形容易判错
真正麻烦的从来不是“怎么画出来”,而是坐标系对齐、缩放同步、事件穿透、无障碍支持(比如 screen reader 怎么读多边形区域)、以及——当 UI 突然说“这个热区要跟着地图一起旋转”时,你才发现 <map></map> 根本不支持 transform。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











