纯html页面无法测面积,必须用leaflet加载地图并结合turf.js的turf.area()计算wgs84坐标系下的真实地表面积(平方米),注意坐标格式为[lng,lat]、环方向需逆时针,可借助turf.rewind修正。

用 Leaflet + Turf.js 实现点击画多边形测面积
直接说结论:纯 HTML 页面做不到“测面积”,必须引入地理空间计算库。浏览器原生不提供平面/球面多边形面积计算能力,canvas 或 svg 自己描点只能拿到像素坐标,换算成真实平方米会严重失真——尤其跨纬度时误差可达 20% 以上。
实际可行路径是:HTML 页面加载地图(如 Leaflet),用户用鼠标绘制闭合多边形,再交由 turf.area() 计算 WGS84 坐标系下的真实地表面积(单位:平方米)。
- Leaflet 负责渲染底图、交互绘制(用
L.drawControl插件) - Turf.js 负责几何运算——它不依赖地图,只认 GeoJSON 格式坐标数组
- 关键点:绘制结束触发的
draw:created事件里,把event.layer.toGeoJSON()传给turf.area() - 注意 turf.area 返回的是平方米,若需公顷或平方公里,自己除以
10000或1000000
为什么不能用 canvas.getContext('2d').isPointInPath?
isPointInPath 只能判断点是否在路径内,完全不涉及面积计算;更关键的是,它工作在屏幕像素坐标系,而地图投影(如 Web Mercator)会让高纬度区域严重拉伸——同一像素宽,在赤道约等于 78 米,在北纬 60° 就只剩约 39 米。直接套用像素面积公式 width * height 会彻底失效。
常见错误现象:turf.area() 返回值为 0 或 NaN,大概率是传入的 GeoJSON 坐标顺序反了(环方向必须是逆时针表示外环),或坐标不是 [lng, lat] 格式(Turf 严格要求经度在前)。
- 检查坐标格式:打印
feature.geometry.coordinates[0][0],确保是类似[116.4, 39.9]而非[39.9, 116.4] - 自动修正环方向:用
turf.rewind(feature, { reverse: true })强制转为标准环向 - 避免用
map.getPixelBounds()算面积——那是视口像素范围,和地理面积无关
离线使用 Turf.js 的最小依赖方案
如果部署环境无法联网加载 CDN,不要下载整个 turf.min.js(2MB+),它包含 150+ 功能模块,测面积只需 turf.area 和 turf.rewind 两个函数。
推荐做法:用 npm 安装子模块:npm install @turf/area @turf/rewind,再用 ES6 import:
import area from '@turf/area'; import rewind from '@turf/rewind';
打包后体积可压到 30KB 以内。若连 npm 都不能用,去 unpkg 单独扒 @turf/area 源码(注意它依赖 @turf/invariant,需一并引入)。
- 别用
script标签直接引用未打包的 ES Module 文件——浏览器会报TypeError: Failed to resolve module specifier - CDN 加载失败时,
turf全局变量不存在,要加if (typeof turf === 'undefined')容错 - Leaflet 版本建议锁定 1.9.x,2.0+ 已移除
L.drawControl,需改用@geoman-io/leaflet-geoman
移动端触摸绘制的兼容处理
Leaflet 默认支持 touch,但 L.Draw.Polygon 在 iOS Safari 上可能出现点位偏移或漏点——根本原因是 touchmove 事件默认行为被页面滚动拦截了。
必须加两行 CSS 防止误操作:
html, body { touch-action: none; }
#map { touch-action: manipulation; }
否则用户手指刚画两下,页面就跟着上下滚动,多边形直接废掉。
- Android Chrome 一般没问题,但部分国产浏览器(如 UC、QQ 浏览器)需要额外监听
touchstart并调用event.preventDefault() - 用
L.point(event.containerPoint.x, event.containerPoint.y)获取触摸位置,别用event.touches[0].clientX直接算——坐标系不一致 - 双击结束绘制在移动端容易误触,建议关闭:
draw: { polygon: { allowIntersection: false, drawError: { timeout: 0 } } }
真正麻烦的不是代码怎么写,而是搞清“哪个坐标系、哪个单位、哪段坐标数据该喂给哪个函数”。少查一次投影文档,面积就差一个数量级。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











