canvas实现区域点击映射的关键是将地理区域建模为多边形,通过点在多边形内算法(如射线法)判定鼠标位置;需准备顶点坐标数组,监听click事件并换算屏幕坐标,再逐区域检测命中,最后触发高亮、下钻或回调等业务逻辑。

Canvas本身不提供“元素级”点击识别,实现区域点击映射的关键在于:把每个地理区域(如省份、地级市)视为一个数学多边形,通过点在多边形内的算法判断鼠标是否落在该区域上。
准备带坐标的区域数据
必须有每个区域的边界顶点坐标数组,格式通常是[[x1,y1], [x2,y2], …]。这些坐标可以是:
- 原始经纬度(需经墨卡托或等距圆柱投影转换为屏幕像素坐标)
- 已预处理好的归一化平面坐标(0–1范围,适配任意画布尺寸)
- 直接来自GeoJSON的
coordinates字段,但要注意MultiPolygon需展开
例如江苏的轮廓可能存为jiangsu: [[100,240], [105,238], …],它不是DOM节点,而是一组纯数字。
监听点击并换算屏幕坐标
Canvas没有内置事件委托,需手动绑定click事件,并将鼠标位置转为相对于Canvas左上角的像素坐标:
- 用
canvas.getBoundingClientRect()获取画布在视口中的真实位置 - 减去
event.clientX/clientY与左上角的偏移,得到canvasX和canvasY - 若画布被CSS缩放,还需除以
devicePixelRatio或应用transform逆矩阵
执行点在多边形内判定
这是核心逻辑,常用射线法(Ray Casting)或 winding number 法。一个轻量可靠的实现如下:
- 遍历该区域所有线段,统计从测试点向右水平发射的射线与多少条边相交
- 相交次数为奇数 → 点在内部;偶数 → 在外部或边上
- 对每个省/市循环调用该函数,最先返回
true的那个即为命中区域
注意:若区域含洞(如海南岛+西沙群岛),需用更严谨的GeoJSON拓扑解析,不能简单合并所有环。
绑定业务行为与反馈
判定成功后,即可触发具体交互:
- 高亮该区域:重绘时对该多边形使用不同
fillStyle或加描边 - 展开下级:比如点击“广东省”,加载并绘制
guangdongCities数组里的21个地级市多边形 - 回调通知:执行
onProvinceClick('广东', x, y),由上层决定弹窗、跳转或请求数据 - 避免误触:可加最小点击面积阈值(如3×3像素)或防抖
整个过程不依赖DOM查找,不生成数百个<path></path>,因此性能稳定,适合低端设备和大屏看板。











