还在用老方法计算面积距离?Turf.js文档核心API速查(附实战案例)
如果你在 WebGIS 项目里还在用老方法计算面积距离?Turf.js文档核心API速查(附实战案例)这篇文章可以帮你快速切换到更稳定、更适合前端地图的做法。Turf.js 是一个常用于浏览器和 Node.js 环境的 JavaScript 空间分析库,适合处理 GeoJSON 数据的距离、面积、缓冲区、叠加分析、点线面判断等任务。
本文不做泛泛的 API 罗列,而是围绕 GIS 开发中最常见的几个问题:测距、算面积、判断点是否在面内、生成缓冲区、裁剪叠加和统计分析,整理 Turf.js 文档里的核心 API,并给出可直接改造到 Leaflet、OpenLayers 或 Mapbox GL JS 项目中的实战写法。

引言:为什么 WebGIS 项目需要 Turf.js 文档核心API速查
很多 GIS 初学者或前端开发者在实现地图测距、面积统计时,习惯自己写球面距离公式,或者把数据传回后端 GIS 服务计算。这样并不是不能用,但在交互式 WebGIS 场景下,经常会遇到三个问题:
- 代码分散,面积、距离、缓冲区、空间判断各写一套逻辑。
- 坐标单位、投影单位、球面距离混用,导致结果不稳定。
- 每次交互都请求后端,前端响应慢,用户体验差。
Turf.js 的优势在于:它直接以 GeoJSON 为输入输出格式,和 WebGIS 前端天然兼容。只要你的地图数据可以转成 GeoJSON,就可以用 Turf.js 快速完成轻量级空间分析。
建议把 Turf.js 理解为“前端空间分析工具箱”,而不是完整替代 PostGIS、ArcGIS Server 或 GeoServer 的 GIS 引擎。它适合轻量、实时、交互式分析,不适合超大规模批处理。
背景:Turf.js 适合解决哪些 GIS 问题
Turf.js 最常见的使用场景集中在 WebGIS 前端交互分析。比如用户在地图上画一条线后,需要立即显示长度;圈选一个区域后,需要计算面积;点击一个点后,需要判断它属于哪个行政区;上传一个 GeoJSON 后,需要快速做缓冲区分析。
这些需求有一个共同点:数据量通常不大,但要求即时反馈。此时如果每一步都调用后端空间数据库,开发成本和交互延迟都会增加。Turf.js 正好适合放在前端完成这些中小规模计算。
常见应用场景
- 地图测距:计算线段长度、两点距离、路径总长度。
- 面积统计:计算用户绘制面、行政区面、地块面的面积。
- 空间查询:判断点是否在多边形内,筛选落入范围内的点。
- 缓冲区分析:围绕点、线、面生成一定距离范围。
- 叠加分析:计算相交区域、裁剪范围、合并面要素。
- 数据辅助处理:获取中心点、边界框、随机点、简化线面。
原理:使用 Turf.js 计算面积距离前必须理解的三件事
在看 Turf.js 文档核心 API 之前,先理解三个基本概念,可以避免大部分面积和距离计算错误。
1. Turf.js 主要处理 GeoJSON
GeoJSON 是 WebGIS 中常见的空间数据格式。Turf.js 的函数通常接收 GeoJSON 的 Feature、FeatureCollection、Geometry 作为参数,并返回新的 GeoJSON 对象或数值结果。
const point = turf.point([116.391, 39.907]);
const line = turf.lineString([
[116.391, 39.907],
[116.401, 39.917]
]);
这里的坐标顺序是 [经度, 纬度],也就是 [longitude, latitude]。这是很多新手最容易写反的地方。
2. 距离和面积不要直接按经纬度做平面计算
经纬度坐标的单位是度,不是米。如果直接用普通平面几何公式计算面积距离,结果通常不可靠。Turf.js 的 distance、length、area 等函数会按地理坐标场景进行处理,更适合 WebGIS 常见的 WGS84 经纬度数据。
但要注意:如果你的数据已经是投影坐标,比如 CGCS2000 高斯投影、Web Mercator 米制坐标,使用 Turf.js 前要确认坐标是否需要转换为经纬度 GeoJSON。
3. 前端空间分析要控制数据规模
Turf.js 可以在浏览器里运行,但浏览器不是空间数据库。几百、几千个要素的交互分析通常没问题;如果你要对几十万条道路、上百万个点做叠加分析,应优先考虑 PostGIS、GeoPandas、ArcGIS Pro 或服务端 GIS 引擎。
步骤:Turf.js 文档核心API速查与实战写法
下面按实际开发频率整理 Turf.js 核心 API。示例均以浏览器或现代前端项目中常见的写法为主。
步骤 1:安装或引入 Turf.js
如果你使用 Vite、Vue、React、Webpack 等现代前端工程,推荐通过 npm 安装:
npm install @turf/turf
在代码中引入:
import * as turf from '@turf/turf';
如果是传统 HTML 页面,也可以通过 CDN 引入:
<script src="https://cdn.jsdelivr.net/npm/@turf/turf@7/turf.min.js"></script>
实际项目中建议固定版本号,避免线上依赖因版本变化导致 API 行为不一致。
步骤 2:计算两点距离 distance
turf.distance 用于计算两个点之间的距离。它非常适合点击地图两个位置后显示直线距离。
const from = turf.point([116.391, 39.907]);
const to = turf.point([116.421, 39.932]);
const distanceKm = turf.distance(from, to, { units: 'kilometers' });
const distanceM = turf.distance(from, to, { units: 'meters' });
console.log('距离(千米):', distanceKm);
console.log('距离(米):', distanceM);
常用单位包括 kilometers、meters、miles。在中文 GIS 项目中,建议统一使用米或千米,并在界面上明确显示单位。
步骤 3:计算线长度 length
turf.length 用于计算 LineString 或 MultiLineString 的长度,适合路线长度、巡检路径长度、河流长度等场景。
const route = turf.lineString([
[116.391, 39.907],
[116.401, 39.917],
[116.421, 39.932]
]);
const length = turf.length(route, { units: 'kilometers' });
console.log('路线长度(千米):', length);
如果你在 Leaflet 或 OpenLayers 中让用户绘制折线,可以把绘制结果转为 GeoJSON 后交给 turf.length 计算。
步骤 4:计算多边形面积 area
turf.area 是 Turf.js 计算面积最常用的 API。它返回的面积单位是平方米。
const polygon = turf.polygon([[
[116.391, 39.907],
[116.421, 39.907],
[116.421, 39.927],
[116.391, 39.927],
[116.391, 39.907]
]]);
const areaM2 = turf.area(polygon);
const areaKm2 = areaM2 / 1000000;
console.log('面积(平方米):', areaM2);
console.log('面积(平方千米):', areaKm2);
注意多边形坐标环必须闭合,也就是第一个坐标点和最后一个坐标点相同。很多面积计算失败或结果异常,都是因为面要素坐标环不合法。
步骤 5:判断点是否在面内 booleanPointInPolygon
turf.booleanPointInPolygon 用于判断一个点是否位于多边形内部,常用于行政区归属判断、围栏告警、点位筛选。
const pt = turf.point([116.400, 39.915]);
const district = turf.polygon([[
[116.391, 39.907],
[116.421, 39.907],
[116.421, 39.927],
[116.391, 39.927],
[116.391, 39.907]
]]);
const inside = turf.booleanPointInPolygon(pt, district);
console.log('点是否在面内:', inside);
如果点正好落在边界上,要结合业务规则判断是否算作“在范围内”。不同系统对边界点的处理可能不同,建议在需求文档中写清楚。
步骤 6:生成缓冲区 buffer
turf.buffer 可以围绕点、线或面生成指定距离的缓冲区。它常用于服务半径、道路影响范围、设施覆盖范围分析。
const school = turf.point([116.391, 39.907]);
const buffer = turf.buffer(school, 500, { units: 'meters' });
console.log(buffer);
如果你要把缓冲区显示到地图上,直接把返回的 GeoJSON 添加到图层即可。需要注意的是,缓冲区结果通常是 Polygon 或 MultiPolygon,点数可能比原始数据多,会增加前端渲染压力。
步骤 7:计算相交区域 intersect
turf.intersect 用于计算两个面要素的相交部分。适合判断两个区域是否重叠,或计算重叠面积。
const areaA = turf.polygon([[
[116.391, 39.907],
[116.421, 39.907],
[116.421, 39.927],
[116.391, 39.927],
[116.391, 39.907]
]]);
const areaB = turf.polygon([[
[116.405, 39.915],
[116.435, 39.915],
[116.435, 39.935],
[116.405, 39.935],
[116.405, 39.915]
]]);
const fc = turf.featureCollection([areaA, areaB]);
const intersection = turf.intersect(fc);
if (intersection) {
const overlapArea = turf.area(intersection);
console.log('相交面积(平方米):', overlapArea);
} else {
console.log('两个区域不相交');
}
不同 Turf.js 版本中部分叠加分析函数的参数形式可能有变化。实际项目中请以当前安装版本的官方文档为准,并在升级依赖后补充单元测试。
步骤 8:筛选范围内点 pointsWithinPolygon
turf.pointsWithinPolygon 可以从点集合中筛选落入多边形范围内的点。它常用于门店圈选、监测点统计、兴趣点筛选。
const points = turf.featureCollection([
turf.point([116.400, 39.915], { name: '点A' }),
turf.point([116.450, 39.950], { name: '点B' })
]);
const polygon = turf.polygon([[
[116.391, 39.907],
[116.421, 39.907],
[116.421, 39.927],
[116.391, 39.927],
[116.391, 39.907]
]]);
const selected = turf.pointsWithinPolygon(points, polygon);
console.log('范围内点数量:', selected.features.length);
console.log(selected);
步骤 9:获取中心点 center、centroid、centerOfMass
Turf.js 里有多个“中心点”相关 API,容易混淆:
turf.center:根据要素边界框计算中心点。turf.centroid:根据顶点平均位置计算质心。turf.centerOfMass:更接近几何面质量中心的计算方式。
const poly = turf.polygon([[
[116.391, 39.907],
[116.421, 39.907],
[116.421, 39.927],
[116.391, 39.927],
[116.391, 39.907]
]]);
const c1 = turf.center(poly);
const c2 = turf.centroid(poly);
const c3 = turf.centerOfMass(poly);
console.log(c1, c2, c3);
如果只是地图定位到区域中心,通常用 center 就够了。如果要给面状地块放置标注,建议实际测试 centroid 或 centerOfMass 的显示效果。
步骤 10:简化线面 simplify
turf.simplify 用于减少线或面的节点数量,适合 WebGIS 前端性能优化。
const simplified = turf.simplify(polygon, {
tolerance: 0.001,
highQuality: false
});
console.log(simplified);
tolerance 越大,简化越明显,但形状失真也越大。对于行政边界、地块边界等严肃业务数据,不建议在未评估误差的情况下直接简化后参与面积统计。
常见坑:Turf.js计算面积距离结果不对的原因
坑 1:经纬度顺序写反
GeoJSON 坐标顺序是 [经度, 纬度],不是很多地图 API 页面上常见的“纬度、经度”描述。如果把北京坐标写成 [39.907, 116.391],点会跑到错误位置,后续面积距离计算全部失真。
坑 2:把投影坐标当经纬度传给 Turf.js
如果你的坐标类似 [12958175, 4852341],很可能是 Web Mercator 或其他米制投影坐标,不是经纬度。此时直接用 Turf.js 的距离、面积函数,结果会很容易异常。
处理建议:
- 确认数据坐标系,尤其是 EPSG 代码。
- 前端分析前尽量转换为 WGS84 经纬度 GeoJSON。
- 如果需要严格投影面积,考虑在后端用 PostGIS 或 GDAL 处理。
坑 3:多边形没有闭合或自相交
GeoJSON Polygon 的每个线性环必须闭合。自相交多边形、重复点、空洞环方向错误等问题,都会让面积和叠加分析结果变得不可靠。
在生产环境中,建议对用户绘制或上传的数据做合法性校验。对于复杂面数据,可以在服务端用 PostGIS 的 ST_IsValid、ST_MakeValid 或 GIS 桌面软件先清洗。
坑 4:用 Turf.js 处理过大的数据集
Turf.js 运行在浏览器时,会占用用户设备的 CPU 和内存。点面筛选、缓冲区、叠加分析在数据量大时非常消耗性能。如果页面卡顿,不要只怀疑地图框架,也要检查 Turf.js 分析的数据量。
坑 5:忽略单位参数
distance、length、buffer 等函数都和单位有关。团队开发时建议封装统一函数,避免有人用米,有人用千米,最后导致结果差 1000 倍。
方法比较:Turf.js、PostGIS、ArcGIS Pro 和 GeoPandas 怎么选
| 方法 | 适合场景 | 优势 | 限制 |
|---|---|---|---|
| Turf.js | WebGIS 前端轻量分析、交互测量、范围筛选 | 直接处理 GeoJSON,前端响应快,集成简单 | 不适合超大数据量和高精度复杂空间分析 |
| PostGIS | 服务端空间查询、海量数据筛选、空间索引分析 | 性能强,可建空间索引,适合生产数据库 | 需要数据库和后端接口支持 |
| ArcGIS Pro | 桌面 GIS 制图、专业空间分析、批处理建模 | 工具完整,适合规范化 GIS 作业 | 不适合直接承担前端实时交互计算 |
| GeoPandas | Python 数据分析、批量矢量处理、科研统计 | 适合脚本化处理和数据分析流程 | 需要 Python 环境,对前端交互不直接友好 |
简单判断:如果是浏览器里即时反馈的小规模空间分析,优先用 Turf.js;如果是海量数据查询和严肃业务统计,优先用 PostGIS 或后端 GIS 服务;如果是离线制图和批处理,ArcGIS Pro、QGIS、GeoPandas 更合适。
检查清单:上线前如何检查 Turf.js 面积距离功能
- 坐标顺序:确认所有 GeoJSON 坐标都是
[经度, 纬度]。 - 坐标系:确认输入数据是否为 WGS84 经纬度,避免投影坐标误用。
- 单位:统一距离和缓冲区单位,界面显示与计算单位一致。
- 几何合法性:检查多边形是否闭合,是否存在自相交或空几何。
- 数据规模:避免在浏览器中一次性叠加分析超大数据集。
- 边界规则:明确点落在面边界时是否算作在范围内。
- 版本锁定:固定
@turf/turf版本,升级前回归测试核心 API。 - 结果校验:用 QGIS、ArcGIS Pro 或 PostGIS 抽样对比关键计算结果。
FAQ:Turf.js文档核心API常见问题
Turf.js 计算面积准吗?
对于常见 WebGIS 经纬度 GeoJSON 的轻量面积计算,turf.area 可以满足很多前端展示和交互统计需求。但如果涉及法定面积、工程测量、地籍权属等高精度业务,应使用合适的投影坐标系,并在专业 GIS 软件或后端空间分析环境中计算和复核。
Turf.js 计算距离应该用 distance 还是 length?
两点之间的直线距离用 turf.distance;一条折线或路径的总长度用 turf.length。如果用户在地图上画了一条多段线,应使用 length,而不是只计算起点到终点的距离。
Turf.js 能不能直接处理 Shapefile?
Turf.js 主要处理 GeoJSON,不能直接把 Shapefile 当作输入。你可以先在后端或前端使用相关工具把 Shapefile 转为 GeoJSON,再交给 Turf.js 分析。生产项目中更推荐在服务端完成格式转换和数据清洗。
Turf.js 和 Leaflet、OpenLayers 是什么关系?
Leaflet 和 OpenLayers 主要负责地图显示、图层管理和交互操作;Turf.js 负责空间分析计算。实际项目中常见做法是:用户在 Leaflet 或 OpenLayers 上绘制几何,转换成 GeoJSON 后交给 Turf.js 计算,再把结果渲染回地图。
为什么 Turf.js buffer 生成的缓冲区看起来不够圆?
缓冲区本质上是用多边形近似表达圆形或曲线区域。显示效果和分段数量、地图缩放级别、数据坐标有关。如果对视觉效果要求较高,可以检查 buffer 参数和地图渲染样式;如果对精度要求较高,应在专业 GIS 环境中验证。
Turf.js 能替代 PostGIS 吗?
不能简单替代。Turf.js 更适合前端轻量空间分析,PostGIS 更适合服务端空间数据库、空间索引、复杂查询和海量数据处理。两者在 WebGIS 架构中通常是互补关系。
结论:把 Turf.js 用在合适的位置,面积距离计算会更稳
Turf.js 文档核心API速查的重点,不是记住所有函数名,而是知道在什么场景用哪个 API。两点距离用 distance,线长度用 length,面面积用 area,点面判断用 booleanPointInPolygon,缓冲区用 buffer,范围筛选用 pointsWithinPolygon。
在 WebGIS 项目中,Turf.js 非常适合承担前端轻量级空间分析任务。只要你控制好坐标系、单位、几何合法性和数据规模,就可以用更少的代码实现可靠的面积距离计算和交互分析。
最后建议把常用 Turf.js API 封装成项目内部工具函数,并配合 QGIS、PostGIS 或 ArcGIS Pro 做抽样校验。这样既能保持前端交互流畅,也能让 GIS 计算结果更可信。