前端GIS开发如何实现地理分析?Turf.js中文API下载,含离线版手册!

编程与开发
Dr.GIS
wowwwai GIS研习社 · 工具流程与项目排障

前端GIS开发如何实现地理分析?Turf.js中文API下载,含离线版手册!这类问题通常出现在 WebGIS 项目进入“查询、统计、缓冲区、叠加分析、空间判断”阶段:底图和图层已经能加载,但一旦要在浏览器端做地理分析,就不知道该用后端 GIS 服务、PostGIS,还是直接在前端用 Turf.js。

本文以前端 GIS 开发为场景,讲清楚 Turf.js 适合解决哪些地理分析问题,如何在 Leaflet、OpenLayers 或原生 JavaScript 项目中使用 Turf.js API,并整理离线查阅中文 API 手册时应该重点关注的模块。你可以把它当作一份 Turf.js 中文 API 使用指南,而不是简单的函数列表。

前端GIS开发地理分析 Turf.js中文API离线手册流程图
前端 GIS 中使用 Turf.js 执行地理分析的一般流程:输入 GeoJSON,调用分析 API,再把结果渲染到地图。

引言:为什么前端GIS开发会需要 Turf.js 地理分析

很多 WebGIS 项目一开始只需要展示点、线、面数据,例如门店位置、巡检轨迹、行政区边界、管线图层等。但随着业务深入,需求会变成:

  • 判断一个点是否落在某个行政区或服务范围内;
  • 计算两个点之间的距离;
  • 给线或点生成缓冲区;
  • 统计某个多边形范围内有多少个点;
  • 把两个面图层做相交、合并、裁剪等分析;
  • 根据前端绘制的范围实时筛选数据。

这些都是典型的地理分析需求。如果每次都请求后端 GIS 服务,开发成本和接口延迟都会增加。对于中小数据量、交互式分析、临时绘制分析范围等场景,Turf.js 是前端 GIS 开发中非常实用的空间分析库。

背景:Turf.js 适合解决什么问题

Turf.js 是一个面向 JavaScript 的地理空间分析库,主要处理 GeoJSON 数据。GeoJSON 是 WebGIS 中常见的空间数据格式,使用 JSON 表达点、线、面及其属性。

在前端 GIS 开发中,Turf.js 的价值主要体现在三类场景:

  • 轻量空间判断:例如点是否在面内、线是否相交、两个图形是否重叠。
  • 交互式空间计算:例如用户在地图上画一个面,前端立即计算面积、筛选点、生成缓冲区。
  • GeoJSON 数据处理:例如合并要素、提取中心点、计算边界框、简化几何。

需要注意的是,Turf.js 不是 PostGIS、ArcGIS Server 或 GeoServer 的替代品。它更适合浏览器端的即时分析,而不是大规模空间数据处理。如果数据量很大、拓扑关系复杂、需要严格投影计算,仍然建议放到后端 GIS 或数据库中完成。

原理:Turf.js 为什么能在浏览器端做地理分析

Turf.js 的核心思路是:把空间对象统一表示为 GeoJSON,然后通过 JavaScript 函数对这些几何对象进行计算。

例如,一个点可以写成:

const point = {
  type: "Feature",
  geometry: {
    type: "Point",
    coordinates: [116.397, 39.908]
  },
  properties: {
    name: "示例点"
  }
};

一个多边形可以写成:

const polygon = {
  type: "Feature",
  geometry: {
    type: "Polygon",
    coordinates: [[
      [116.30, 39.80],
      [116.50, 39.80],
      [116.50, 40.00],
      [116.30, 40.00],
      [116.30, 39.80]
    ]]
  },
  properties: {
    name: "示例范围"
  }
};

Turf.js 的 API 会接收这些 GeoJSON 对象,然后返回布尔值、数值或新的 GeoJSON 要素。例如点面判断返回 true 或 false,缓冲区分析返回一个新的面要素。

这也是为什么学习 Turf.js 中文 API 时,首先要熟悉 GeoJSON 的基本结构。如果输入数据不是合法 GeoJSON,很多 Turf.js API 会直接报错,或者计算结果看起来不符合预期。

步骤:前端GIS开发如何使用 Turf.js API

步骤一:安装或引入 Turf.js

如果你的项目使用 npm,可以直接安装:

npm install @turf/turf

在模块化项目中引入:

import * as turf from "@turf/turf";

如果是普通 HTML 页面,也可以通过 script 标签引入打包后的 Turf.js 文件。离线项目可以把 turf.min.js 下载到本地,再从本地路径加载。

<script src="./libs/turf.min.js"></script>

离线部署时建议把 Turf.js 文件和项目代码一起纳入版本管理,避免生产环境依赖外部 CDN。

步骤二:准备标准 GeoJSON 数据

Turf.js 的输入通常是 GeoJSON Feature 或 FeatureCollection。不要直接把 Leaflet 的图层对象、OpenLayers 的 Feature 对象传给 Turf.js,应该先转换成 GeoJSON。

Leaflet 中常见写法:

const geojson = leafletLayer.toGeoJSON();

OpenLayers 中常见写法:

import GeoJSON from "ol/format/GeoJSON";

const format = new GeoJSON();
const geojson = format.writeFeatureObject(olFeature, {
  featureProjection: "EPSG:3857",
  dataProjection: "EPSG:4326"
});

这里要特别注意坐标系。Turf.js 通常按经纬度坐标使用,也就是 EPSG:4326。如果你直接把 EPSG:3857 的米制坐标传入 Turf.js,距离、面积、缓冲区结果很容易异常。

步骤三:计算两个点之间的距离

距离计算是 Turf.js 中文 API 中最常用的能力之一。示例代码如下:

const from = turf.point([116.397, 39.908]);
const to = turf.point([121.473, 31.230]);

const distance = turf.distance(from, to, {
  units: "kilometers"
});

console.log("距离:", distance, "公里");

这里的坐标顺序是经度在前、纬度在后,即 [longitude, latitude]。很多前端 GIS 初学者会把纬度写在前面,导致计算结果完全错误。

步骤四:判断点是否在多边形内

点面判断适合做行政区归属、服务范围判断、围栏判断等业务。

const pt = turf.point([116.397, 39.908]);

const area = turf.polygon([[
  [116.30, 39.80],
  [116.50, 39.80],
  [116.50, 40.00],
  [116.30, 40.00],
  [116.30, 39.80]
]]);

const inside = turf.booleanPointInPolygon(pt, area);

console.log("点是否在范围内:", inside);

如果你的多边形来自后台接口,建议先检查首尾坐标是否闭合。GeoJSON 的 Polygon 外环通常要求第一个坐标和最后一个坐标一致。

步骤五:生成缓冲区

缓冲区分析常用于“某点周边 1 公里”“某条线路两侧 500 米”“设施影响范围”等场景。

const center = turf.point([116.397, 39.908]);

const buffer = turf.buffer(center, 1, {
  units: "kilometers"
});

console.log(buffer);

生成的 buffer 仍然是 GeoJSON,可以直接添加到 Leaflet 或 OpenLayers 地图中显示。

Leaflet 示例:

L.geoJSON(buffer, {
  style: {
    color: "#ff0000",
    weight: 2,
    fillOpacity: 0.2
  }
}).addTo(map);

步骤六:统计范围内点数量

前端 GIS 开发中经常需要根据一个面范围筛选点数据。可以结合 booleanPointInPolygon 遍历点集合。

const points = turf.featureCollection([
  turf.point([116.35, 39.90], { name: "A" }),
  turf.point([116.60, 39.90], { name: "B" }),
  turf.point([116.40, 39.95], { name: "C" })
]);

const polygon = turf.polygon([[
  [116.30, 39.80],
  [116.50, 39.80],
  [116.50, 40.00],
  [116.30, 40.00],
  [116.30, 39.80]
]]);

const selected = points.features.filter(feature => {
  return turf.booleanPointInPolygon(feature, polygon);
});

console.log("范围内点数量:", selected.length);

如果点数量达到几万甚至几十万,单纯在浏览器端遍历可能会卡顿。此时应考虑空间索引、Web Worker,或者把筛选逻辑放到后端。

步骤七:叠加分析与裁剪

Turf.js 也提供了一些面与面之间的分析能力,例如相交、合并、差异等。不同版本的 Turf.js 对部分布尔和叠加函数支持情况可能有变化,使用前建议查看对应版本的官方 API 文档或离线手册。

const poly1 = turf.polygon([[
  [116.30, 39.80],
  [116.50, 39.80],
  [116.50, 40.00],
  [116.30, 40.00],
  [116.30, 39.80]
]]);

const poly2 = turf.polygon([[
  [116.40, 39.90],
  [116.60, 39.90],
  [116.60, 40.10],
  [116.40, 40.10],
  [116.40, 39.90]
]]);

const intersects = turf.booleanIntersects(poly1, poly2);

console.log("两个面是否相交:", intersects);

对于复杂多边形的叠加分析,Turf.js 可能受到几何有效性、坐标精度和浏览器性能影响。如果结果异常,建议先用 QGIS 或 PostGIS 检查几何是否有效。

常见坑:Turf.js 中文 API 使用时最容易出错的地方

坑一:经纬度顺序写反

GeoJSON 坐标顺序是 [经度, 纬度],不是 [纬度, 经度]。例如北京大致应写成:

[116.397, 39.908]

如果写成:

[39.908, 116.397]

点会跑到完全错误的位置,距离、面积、点面判断也都会失真。

坑二:把 Web Mercator 坐标直接传给 Turf.js

很多 WebGIS 地图底图使用 EPSG:3857,但 Turf.js 常见计算输入是 EPSG:4326 经纬度。如果你从 OpenLayers 取出的坐标是米制坐标,必须转换后再交给 Turf.js。

典型表现包括:

  • 缓冲区巨大或不可见;
  • 距离结果明显不合理;
  • 点面判断始终为 false;
  • GeoJSON 添加到地图后位置偏移。

坑三:数据量太大导致浏览器卡顿

Turf.js 在浏览器端运行,性能受用户设备影响。几百到几千个要素的交互分析通常比较适合;如果要处理几十万条线或大量复杂面,应该优先考虑后端空间数据库或服务端 GIS 分析。

坑四:多边形无效导致叠加分析失败

自相交、多环关系错误、外环未闭合、坐标精度异常,都可能导致 Turf.js 的面分析结果不稳定。遇到问题时可以先用 QGIS 的“检查有效性”或 PostGIS 的 ST_IsValid 验证几何。

坑五:把地图显示效果误认为真实测量精度

Turf.js 很适合做前端交互分析,但如果你的项目涉及法定面积、工程测量、国土调查等高精度业务,不能只依赖浏览器端经纬度计算。此类场景应使用合适的投影坐标系和经过验证的专业 GIS 工具链。

方法比较:Turf.js、PostGIS、QGIS 与后端 GIS 服务怎么选

方法 适合场景 优点 限制
Turf.js 前端即时分析、绘制范围筛选、轻量 GeoJSON 处理 部署简单,交互快,不一定依赖后端 不适合超大数据量和复杂高精度分析
PostGIS 海量空间数据查询、空间索引、稳定后端分析 性能强,可建立空间索引,适合生产系统 需要数据库设计和后端接口
QGIS 桌面数据检查、制图、批处理分析 可视化强,适合人工处理和验证 不适合直接承担 Web 前端交互分析
GeoServer 或 ArcGIS Server 标准地图服务、企业级空间服务发布 服务能力完整,可统一管理图层 部署和运维成本较高

简单判断:如果分析结果只服务于当前页面交互,数据量不大,且输入输出都是 GeoJSON,优先考虑 Turf.js。如果分析需要长期保存、多人复用、数据量大、涉及权限和审计,建议放到 PostGIS 或 GIS 服务端。

检查清单:使用 Turf.js 做前端地理分析前先确认这些项

  • 输入数据是否为合法 GeoJSON Feature 或 FeatureCollection;
  • 坐标顺序是否为经度在前、纬度在后;
  • 数据坐标系是否已经转换为 EPSG:4326;
  • Polygon 外环是否闭合;
  • 是否存在自相交、空几何、重复点等问题;
  • 距离、面积、缓冲区单位是否设置正确;
  • 浏览器端数据量是否会造成卡顿;
  • 是否需要把复杂计算放到 Web Worker 或后端;
  • 前端显示结果是否与 QGIS 或 PostGIS 抽样验证一致;
  • 当前项目使用的 Turf.js 版本是否与 API 手册一致。

FAQ:Turf.js中文API下载和前端GIS分析常见问题

Turf.js 中文 API 离线手册应该重点看哪些模块?

建议优先看 Measurement、Coordinate Mutation、Feature Conversion、Joins、Booleans、Transformation、Helper 这些模块。前端 GIS 开发中最常用的是距离、面积、中心点、缓冲区、点面判断、相交判断和 GeoJSON 构造函数。

Turf.js 可以替代 ArcGIS 或 QGIS 的空间分析吗?

不能完全替代。Turf.js 适合在浏览器端做轻量地理分析和交互计算。ArcGIS、QGIS、PostGIS 更适合复杂空间处理、批量数据处理、高精度分析和正式成果生产。

为什么 Turf.js 计算的面积和 QGIS 不一样?

常见原因是坐标系、计算模型和单位不同。QGIS 中如果使用投影坐标系计算面积,结果通常以平方米为单位;Turf.js 常基于经纬度数据进行计算,并通过参数指定单位。要比较结果,应确保数据坐标系、单位和计算方法一致。

Turf.js 能处理 Shapefile 吗?

Turf.js 本身主要处理 GeoJSON。Shapefile 需要先转换成 GeoJSON,再交给 Turf.js。可以在后端使用 GDAL 转换,也可以在前端使用相关解析库,但前端解析大型 Shapefile 并不推荐。

Leaflet 和 OpenLayers 都可以配合 Turf.js 吗?

可以。Leaflet 和 OpenLayers 负责地图显示与交互,Turf.js 负责 GeoJSON 空间分析。关键是要在地图图层对象和 GeoJSON 数据之间正确转换,并处理好坐标系。

离线项目如何使用 Turf.js?

可以把 Turf.js 的打包文件下载到本地项目目录,例如 libs/turf.min.js,再通过本地 script 标签引入。模块化项目也可以通过 npm 安装后随构建产物一起打包。离线版手册则建议与项目使用的 Turf.js 版本保持一致,避免 API 名称或参数不匹配。

Turf.js 做缓冲区为什么结果不圆?

缓冲区在地图上看起来不圆,可能与地图投影、显示比例尺、缓冲区步长参数和坐标系有关。在 Web Mercator 地图上,高纬度地区的形状变形更明显。用于严肃测量时,应使用合适的投影坐标系和专业 GIS 分析流程验证。

结论:前端GIS地理分析优先掌握 GeoJSON、坐标系和常用 API

前端GIS开发如何实现地理分析,核心不是记住所有 Turf.js API,而是先理解 GeoJSON 数据结构、坐标顺序、坐标系转换和浏览器端性能边界。Turf.js 中文 API 离线手册可以帮助你快速查函数,但真正落地时要围绕具体业务选择合适的方法。

对于点面判断、距离计算、缓冲区、范围筛选、简单叠加分析,Turf.js 非常适合前端 GIS 项目快速实现交互式分析。对于海量数据、复杂拓扑和高精度成果,则应结合 PostGIS、QGIS 或后端 GIS 服务完成。这样既能保证 WebGIS 交互体验,也能避免把不适合前端承担的空间分析任务硬塞给浏览器。