WebGIS开发入门教程八: 空间分析咋做?Turf.js怎么用?
《WebGIS开发入门教程八: 空间分析咋做?Turf.js怎么用?》这篇文章解决一个很常见的问题:前端地图已经能显示点、线、面了,下一步怎样在浏览器里做缓冲区、距离计算、包含判断、相交分析这类空间分析?如果你正在用 Leaflet、OpenLayers 或 Mapbox GL JS 做 WebGIS,Turf.js 是最容易上手的一套 JavaScript 空间分析库。
引言:WebGIS空间分析为什么要学 Turf.js
很多 WebGIS 初学者会先掌握底图加载、GeoJSON 显示、图层控制和弹窗查询。但实际项目里,用户往往还会提出这些需求:
- 点击一个点,查询 1 公里范围内有哪些设施。
- 画一条路线,计算路线长度。
- 判断一个点是否落在某个行政区范围内。
- 比较两个面数据是否相交或重叠。
- 对前端绘制的图形做缓冲区分析。
这些都属于空间分析。传统做法是把数据提交到后端,由 PostGIS、GeoServer、ArcGIS Server 或 Python GIS 服务处理。Turf.js 的价值在于:当数据量不大、分析逻辑较轻、交互要求较高时,可以直接在浏览器端完成部分空间分析,让 WebGIS 交互更快、更灵活。

背景:WebGIS里常见的空间分析需求
在 WebGIS 开发中,空间分析不是一个抽象概念,而是围绕“空间对象之间的关系和计算”展开。常见需求可以分成几类。
1. 几何量算
几何量算包括距离、长度、面积、中心点、边界框等计算。例如用户在地图上画一条线,系统实时显示线路长度;用户画一个多边形,系统计算面积。
2. 空间关系判断
空间关系判断用于回答“谁和谁有空间关系”。例如点是否在面内、两条线是否相交、两个面是否重叠。这类分析经常用于范围查询、行政区匹配、碰撞检测和空间筛选。
3. 空间处理
空间处理会生成新的几何对象,例如缓冲区、裁剪、合并、差集、简化等。前端常用的是缓冲区、简化和中心点提取。
4. 空间统计
空间统计通常会把空间关系和属性统计结合起来,例如统计某个行政区内的点数量,或者计算一个范围内设施的分类数量。Turf.js 可以处理简单统计,但复杂统计更建议交给后端数据库。
原理:Turf.js到底是什么
Turf.js 是一个面向 GeoJSON 的 JavaScript 空间分析库。它的核心特点是:输入通常是 GeoJSON,输出也通常是 GeoJSON。因此,它非常适合和 Leaflet、OpenLayers、Mapbox GL JS 等 WebGIS 前端框架配合使用。
GeoJSON 是 WebGIS 中最常见的矢量数据格式之一。一个点、线、面都可以用 GeoJSON 表达。Turf.js 读取这些 GeoJSON 要素后,可以进行距离计算、缓冲区分析、叠置判断、面积计算等操作。
理解 Turf.js 时,要抓住三个关键词:
- Feature:带有几何和属性的 GeoJSON 要素,例如一个学校点、一个小区面。
- Geometry:几何对象本身,例如 Point、LineString、Polygon。
- FeatureCollection:多个 Feature 的集合,常用于一组设施点或一组行政区。
在实际项目中,Turf.js 的典型流程是:
- 从地图图层、接口或用户绘制结果中获得 GeoJSON。
- 调用 Turf.js 方法进行空间分析。
- 得到新的 GeoJSON 结果。
- 把结果添加回地图图层显示。
步骤:Turf.js怎么用,先从三个高频案例入手
步骤一:安装或引入 Turf.js
如果是普通 HTML 页面,可以直接通过 CDN 引入 Turf.js:
<script src="https://cdn.jsdelivr.net/npm/@turf/turf@7/turf.min.js"></script>
如果是 Vue、React、Vite 等现代前端项目,推荐使用 npm 安装:
npm install @turf/turf
然后在代码中引入:
import * as turf from '@turf/turf';
如果只使用少量函数,也可以按模块引入以减小打包体积。例如:
import buffer from '@turf/buffer';
import distance from '@turf/distance';
import booleanPointInPolygon from '@turf/boolean-point-in-polygon';
步骤二:用 Turf.js 计算两点距离
距离计算是 WebGIS空间分析 中最适合入门的功能。下面示例计算两个经纬度点之间的距离。
const pointA = turf.point([116.397, 39.908], { name: '天安门附近' });
const pointB = turf.point([116.407, 39.914], { name: '目标点' });
const distanceKm = turf.distance(pointA, pointB, { units: 'kilometers' });
console.log('两点距离:', distanceKm, '公里');
这里需要注意,经纬度坐标顺序是 [经度, 纬度],不是 [纬度, 经度]。这是 GeoJSON 的基本规则,也是初学者最容易写错的地方。
如果你要在页面上展示结果,可以把距离保留两位小数:
const text = distanceKm.toFixed(2) + ' km';
步骤三:用 Turf.js 做缓冲区分析
Turf.js缓冲区 是 WebGIS 中非常常见的前端分析功能。例如用户点击一个点,系统生成 500 米服务范围。
const center = turf.point([116.397, 39.908]);
const bufferPolygon = turf.buffer(center, 0.5, {
units: 'kilometers'
});
console.log(bufferPolygon);
输出的 bufferPolygon 是一个 Polygon 类型的 GeoJSON Feature。你可以把它直接添加到 Leaflet 或 OpenLayers 中显示。
Leaflet 示例:
const bufferLayer = L.geoJSON(bufferPolygon, {
style: {
color: '#ff6600',
weight: 2,
fillColor: '#ffcc66',
fillOpacity: 0.35
}
}).addTo(map);
这个功能适合做服务半径、影响范围、周边查询等交互。但要注意,前端缓冲区适合轻量分析,不适合大规模、高精度的工程级缓冲区计算。
步骤四:判断点是否在面内
点在面内判断是 Turf.js点在面内 的高频用法。例如判断一个用户点击位置是否位于某个行政区、园区或管控范围内。
const point = turf.point([116.397, 39.908]);
const polygon = turf.polygon([[
[116.380, 39.900],
[116.420, 39.900],
[116.420, 39.930],
[116.380, 39.930],
[116.380, 39.900]
]]);
const isInside = turf.booleanPointInPolygon(point, polygon);
console.log('点是否在面内:', isInside);
如果面数据来自接口,一般是 FeatureCollection。你可以遍历每个行政区面,找到包含该点的区域。
const targetPoint = turf.point([116.397, 39.908]);
let matchedArea = null;
areas.features.forEach(function(area) {
if (turf.booleanPointInPolygon(targetPoint, area)) {
matchedArea = area;
}
});
console.log('匹配到的区域:', matchedArea);
步骤五:筛选缓冲区范围内的点
很多项目会把 Turf.js缓冲区 和 Turf.js点在面内 组合起来。例如:点击地图上的一个位置,生成 1 公里缓冲区,然后找出缓冲区内的医院、学校或设备点。
const clickPoint = turf.point([116.397, 39.908]);
const searchArea = turf.buffer(clickPoint, 1, {
units: 'kilometers'
});
const facilities = turf.featureCollection([
turf.point([116.400, 39.910], { name: '设施A' }),
turf.point([116.430, 39.940], { name: '设施B' }),
turf.point([116.392, 39.906], { name: '设施C' })
]);
const result = facilities.features.filter(function(feature) {
return turf.booleanPointInPolygon(feature, searchArea);
});
console.log('范围内设施:', result);
这个逻辑非常适合入门项目:代码短,结果直观,能体现 WebGIS空间分析 的完整流程。
常见坑:Turf.js使用时最容易出错的地方
1. 经纬度顺序写反
GeoJSON 坐标顺序是 [longitude, latitude],也就是 [经度, 纬度]。如果写成 [纬度, 经度],地图上可能定位到完全错误的位置,距离、缓冲区和点在面内判断都会不可靠。
2. 单位没有设置清楚
Turf.js 中很多函数支持 units 参数,例如 kilometers、meters、miles。如果距离或面积结果不符合预期,先检查单位参数。
const d = turf.distance(pointA, pointB, {
units: 'kilometers'
});
3. 把投影坐标当成经纬度使用
Turf.js 主要面向经纬度 GeoJSON 数据。如果你的数据是 Web Mercator 米制坐标,或者来自某个地方投影坐标系,需要先确认是否已经转换为 WGS84 经纬度。否则计算结果可能偏差很大。
4. 前端一次处理太多数据
Turf.js 运行在浏览器端,性能受用户设备影响。如果一次处理几万、几十万个要素,页面可能明显卡顿。大数据量空间分析建议放到 PostGIS、GeoServer、ArcGIS Server 或后端 Python 服务中完成。
5. 面数据没有闭合或几何无效
GeoJSON Polygon 的首尾坐标应闭合,也就是第一个坐标点和最后一个坐标点一致。如果面几何无效,点在面内、相交、裁剪等结果都可能异常。
6. 忽略边界点情况
点刚好落在面边界上时,不同工具或参数对边界的处理可能不同。做权限区、管控区、红线范围这类严肃业务时,建议明确边界规则,并用后端进行最终校验。
方法比较:Turf.js、PostGIS和后端GIS服务怎么选
| 方法 | 适合场景 | 优点 | 限制 |
|---|---|---|---|
| Turf.js | 前端轻量空间分析、交互式缓冲区、距离计算、点在面内判断 | 上手快,不依赖后端,结果可直接在地图上显示 | 不适合超大数据量和高精度工程分析 |
| PostGIS | 数据库级空间查询、空间索引、大规模叠置分析 | 性能强,适合海量数据和复杂查询 | 需要后端接口和数据库维护 |
| GeoServer | 空间数据服务发布、WMS/WFS、服务端过滤 | 标准化程度高,适合企业级数据发布 | 前端交互分析不如 Turf.js 灵活 |
| ArcGIS Server | 企业 GIS 平台、地理处理服务、复杂空间分析 | 功能完整,适合 ArcGIS 体系项目 | 部署和授权成本较高 |
| Python GIS | 批处理、离线分析、自动化数据处理 | 适合复杂流程和数据清洗 | 通常不直接承担前端实时交互 |
简单判断原则是:如果是用户正在地图上交互的小数据量分析,可以优先考虑 Turf.js;如果是正式业务结果、海量数据查询或复杂叠置分析,应优先考虑 PostGIS 或后端 GIS 服务。
检查清单:写一个可用的 Turf.js 空间分析功能前要确认什么
- 数据格式是否是标准 GeoJSON。
- 坐标顺序是否为 [经度, 纬度]。
- 坐标系是否适合 Turf.js 计算,是否需要转换到 WGS84。
- 距离、缓冲区、面积等函数是否设置了正确单位。
- 输入面数据是否闭合,几何是否有效。
- 浏览器端处理的数据量是否可控。
- 分析结果是否需要后端二次校验。
- 结果图层样式是否与原始图层区分明显。
- 是否给用户展示了分析半径、单位和筛选条件。
- 是否处理了空结果、异常数据和接口失败情况。
FAQ:Turf.js空间分析常见问题
Q1:Turf.js可以替代 PostGIS 吗?
不能完全替代。Turf.js 适合浏览器端轻量 WebGIS空间分析,例如距离计算、缓冲区、点在面内判断。PostGIS 更适合大数据量、空间索引、复杂查询和正式业务数据分析。实际项目中,两者经常配合使用。
Q2:Turf.js缓冲区的结果为什么和桌面GIS不完全一样?
可能原因包括坐标系不同、单位设置不同、输入几何精度不同,以及缓冲区生成算法存在差异。Turf.js 更适合前端交互展示,如果是工程级成果,建议使用 QGIS、ArcGIS Pro、PostGIS 或专业后端服务复核。
Q3:Turf.js点在面内判断不准怎么办?
先检查三件事:坐标顺序是否写反,点和面是否在同一坐标系,面几何是否有效。如果点刚好在边界上,还要确认业务上是否把边界点算作面内。
Q4:Turf.js能处理 Shapefile 吗?
Turf.js 不能直接处理 Shapefile。通常需要先把 Shapefile 转为 GeoJSON,再交给 Turf.js 分析。转换可以使用 QGIS、ogr2ogr、GeoPandas 或后端服务完成。
Q5:前端加载 GeoJSON 后再用 Turf.js 分析会不会很卡?
数据量小时通常没问题。若 GeoJSON 文件很大、要素很多、几何特别复杂,浏览器会卡顿。可以先做数据简化、空间切片、服务端过滤,或者把分析放到 PostGIS 中执行。
Q6:Turf.js适合和 Leaflet 还是 OpenLayers 搭配?
两者都可以。Turf.js 关注的是 GeoJSON 空间分析,Leaflet 和 OpenLayers 负责地图渲染。只要能从地图对象中取出 GeoJSON,或者能把 Turf.js 输出的 GeoJSON 加回地图,就可以配合使用。
结论:先用 Turf.js 建立 WebGIS空间分析思维
学习 WebGIS开发 时,不要只停留在“把数据加载到地图上”。真正的业务价值往往来自空间分析:距离是多少、范围内有什么、点属于哪个区域、对象之间是否相交。Turf.js 提供了一个非常适合入门的方式,让你在浏览器里直接完成这些分析。
建议你从三个功能开始练习:距离计算、Turf.js缓冲区、Turf.js点在面内。掌握这三个案例后,再逐步扩展到相交判断、面积计算、中心点提取、范围筛选和结果统计。对于小数据量、强交互的 WebGIS 功能,Turf.js 很实用;对于大数据量和正式业务结果,则应结合 PostGIS 或后端 GIS 服务一起设计。