经纬志
首页 / Turf.js / 教程

长度、面积、中心与包围盒

先看结论

度量类函数是 Turf 最常被调用的部分。它们看起来简单,真正容易出错的只有两处: 单位怎么传、以及「中心」到底指哪一种中心。

最后验证 2026-11-03 · Turf.js 7.x · 更新 2026-10-29 · 引用本文

长度用 length,不是 distance

distance 算两点之间的大圆距离,length 算整条线的累计长度。 把线的坐标数组直接传给 distance 会得到 NaN, 因为它的入参是点要素。

var route = turf.lineString([
  [116.391263, 39.907359],
  [116.407000, 39.899000],
  [116.430000, 39.910000]
]);

var km  = turf.length(route, { units: 'kilometers' });
var mi  = turf.length(route, { units: 'miles' });
var deg = turf.length(route, { units: 'degrees' });

console.log(km.toFixed(3), mi.toFixed(3), deg.toFixed(3));

units 支持 kilometers、miles、 nauticalmiles、meters、feet、 yards、radians、degrees。 不传时默认 kilometers,很容易让「以为拿到米」的代码差三个数量级。

面积恒为平方米

turf.area 没有 units 参数,返回值固定是平方米。 需要平方公里、公顷、亩时自己换算。

var plot = turf.polygon([[
  [116.380, 39.900],
  [116.400, 39.900],
  [116.400, 39.915],
  [116.380, 39.915],
  [116.380, 39.900]
]]);

var m2  = turf.area(plot);
var km2 = m2 / 1e6;
var ha  = m2 / 1e4;
var mu  = m2 / 666.6667;      // 1 亩 ≈ 666.67 平方米

console.log(m2.toFixed(1), km2.toFixed(4), ha.toFixed(2), mu.toFixed(2));

area 用的是球面公式,结果与投影无关,因此不会因为地图缩放而变化。 Web 墨卡托的平面面积在高纬度会严重失真,两者数值不能互相校验。

三种中心,结果不同

函数定义适用
center外包矩形的中心放置注记、视野居中
centroid所有顶点的平均值顶点分布均匀的规则图形
centerOfMass面按面积加权的重心不规则面、需要「落在面内」时
pointOnFeature保证落在几何内部的点标注位置必须在地块内
var c1 = turf.center(plot);        // 外包矩形中心,可能落在面外
var c2 = turf.centroid(plot);      // 顶点平均,L 形地块会偏
var c3 = turf.centerOfMass(plot);  // 面积重心,通常在面内
var c4 = turf.pointOnFeature(plot);// 保证在面内

console.log(turf.getCoord(c1));
console.log(turf.getCoord(c2));
console.log(turf.getCoord(c3));
console.log(turf.getCoord(c4));

狭长或 L 形地块上,三者的差距很明显。放标注优先用 centerOfMass 或 pointOnFeature, 用 center 常出现「标注跑到地块外面」。

包围盒与方位角

bbox 返回 [minX, minY, maxX, maxY], 也就是 [西, 南, 东, 北]。这个顺序与 Leaflet 的 [[南, 西], [北, 东]] 不同,是跨库协作最常见的错位来源。

var box = turf.bbox(plot);              // [116.38, 39.9, 116.4, 39.915]

var boxPolygon = turf.bboxPolygon(box); // 转成面要素
var boxCenter  = turf.center(boxPolygon);

// 与地图库配合时按对方要求重排
var leafletBounds = [[box[1], box[0]], [box[3], box[2]]];   // [[南,西],[北,东]]

console.log(JSON.stringify(boxPolygon.geometry.type));     // "Polygon"
console.log(turf.getCoord(boxCenter));

bboxPolygon 生成的是一个闭合的矩形面,可以直接交给 intersect 做范围裁剪,或者作为 buffer 的粗筛容器。

注意事项

把 GeoJSON 坐标顺序当成 [lat, lng]

Turf 全线遵循 GeoJSON 规范,坐标是 [经度, 纬度]。 从 GPS 设备或某些后端拿到的 [纬度, 经度] 必须先翻转, 否则面积与长度会算出一个看似合理、实际毫无意义的数字。

用 degrees 当米用

units: 'degrees' 返回的是度数,1 度约 111 公里。 把 length(..., {units:'degrees'}) 的结果直接当米展示, 量级会差五个数量级,且不同纬度上的换算比例还不同。

面对自相交多边形求面积

自相交的环会让球面面积公式得到明显偏离真实值的结果,甚至出现负数。入库前用 turf.kinks 检查自相交点,或者先用 turf.rewind 统一环方向。

引用本文

经纬志(2026)。《长度、面积、中心与包围盒》。https://www.jingweizhi.com/turf/tutorial/measurement.html(访问日期 2026-11-03)。