Centroid
Runnable Turf.js example: Centroid. Open the live demo, read the complete source, and copy the file into your project. No build step or API key.
single HTML file · CDN dependencies onlyinterface may contain Chinese labels
Source
<!--
示例:计算中心点 — 对比顶点均值、外包盒中心与面积加权重心
核心逻辑:同一面分别调用 centroid、center、centerOfMass,位置差异直接标注出来
依赖:Turf.js 7 · jsDelivr CDN
-->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta name="robots" content="noindex,follow">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>计算中心点</title>
<style>
html,body{height:100%;margin:0}
body{display:flex;flex-direction:column;overflow:hidden;
font:13px/1.6 -apple-system,"Segoe UI","PingFang SC",sans-serif;color:#16181d;background:#fff}
.bar{flex:0 0 auto;display:flex;gap:14px;align-items:center;padding:8px 12px;
background:#f6f7f9;border-bottom:1px solid #e3e6ea;font-size:12px;color:#58606e;flex-wrap:wrap}
.bar i{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:5px}
svg{flex:1 1 auto;min-height:0;width:100%;display:block;background:#fbfcfd}
.out{flex:0 0 auto;display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:4px 18px;
padding:8px 12px;border-top:1px solid #e3e6ea;
font-family:ui-monospace,Consolas,monospace;font-size:11.5px;color:#3a4250}
.out b{color:#1f5fd0}
</style>
</head>
<body>
<div class="bar">
<span><i style="background:#c2410c"></i>顶点均值 centroid</span>
<span><i style="background:#1f5fd0"></i>外包盒中心 center</span>
<span><i style="background:#17694a"></i>面积重心 centerOfMass</span>
</div>
<svg id="stage" viewBox="0 0 640 320" preserveAspectRatio="xMidYMid meet"></svg>
<div class="out">
<span>centroid <b id="c1">—</b></span>
<span>center <b id="c2">—</b></span>
<span>centerOfMass <b id="c3">—</b></span>
<span>两个中心相距 <b id="gap">—</b></span>
</div>
<script src="https://cdn.jsdelivr.net/npm/@turf/turf@7/turf.min.js"></script>
<script>
(function () {
'use strict';
if (typeof turf === 'undefined') {
document.body.innerHTML =
'<div style="padding:24px;color:#b42318">Turf.js 加载失败,请检查能否访问 cdn.jsdelivr.net</div>';
return;
}
var W = 640, H = 320, PAD = 34;
var stage = document.getElementById('stage');
/* U 形地块:上方中间凹进去,顶点均值会落到这个缺口里 */
var polygon = turf.polygon([[
[116.280, 39.860], [116.520, 39.860], [116.520, 40.020],
[116.440, 40.020], [116.440, 39.920], [116.360, 39.920],
[116.360, 40.020], [116.280, 40.020], [116.280, 39.860]
]]);
var BOX = [116.24, 39.83, 116.56, 40.05];
var kx = Math.cos(((BOX[1] + BOX[3]) / 2) * Math.PI / 180);
var x0 = BOX[0] * kx, x1 = BOX[2] * kx;
var y0 = BOX[1], y1 = BOX[3];
var s = Math.min((W - PAD * 2) / (x1 - x0), (H - PAD * 2) / (y1 - y0));
var ox = (W - (x1 - x0) * s) / 2;
var oy = (H - (y1 - y0) * s) / 2;
function pr(c) {
return [(c[0] * kx - x0) * s + ox, (y1 - c[1]) * s + oy];
}
function ringPath(ring) {
var d = '';
for (var i = 0; i < ring.length; i++) {
var p = pr(ring[i]);
d += (i ? 'L' : 'M') + p[0].toFixed(1) + ' ' + p[1].toFixed(1);
}
return d + 'Z';
}
var centroid = turf.centroid(polygon);
var center = turf.center(polygon);
var mass = turf.centerOfMass(polygon);
var parts = ['<rect x="0" y="0" width="640" height="320" fill="none" stroke="#e3e6ea"/>'];
parts.push('<path d="' + ringPath(polygon.geometry.coordinates[0]) +
'" fill="rgba(31,95,208,0.07)" stroke="#1f5fd0" stroke-width="1.5"/>');
polygon.geometry.coordinates[0].forEach(function (c) {
var p = pr(c);
parts.push('<circle cx="' + p[0].toFixed(1) + '" cy="' + p[1].toFixed(1) +
'" r="2.4" fill="#8a929f"/>');
});
function pin(feature, color, label, r, dx, dy, anchor) {
var p = pr(feature.geometry.coordinates);
var out = '<circle cx="' + p[0].toFixed(1) + '" cy="' + p[1].toFixed(1) +
'" r="' + r + '" fill="' + color + '" stroke="#fff" stroke-width="2"/>';
out += '<text x="' + (p[0] + dx).toFixed(1) + '" y="' + (p[1] + dy).toFixed(1) +
'" font-size="11" text-anchor="' + (anchor || 'start') +
'" fill="' + color + '">' + label + '</text>';
return out;
}
parts.push(pin(centroid, '#c2410c', 'centroid', 5, -10, 4, 'end'));
parts.push(pin(center, '#1f5fd0', 'center', 5, 10, -8, 'start'));
parts.push(pin(mass, '#17694a', 'centerOfMass', 5, 10, 14, 'start'));
stage.innerHTML = parts.join('');
function fmt(f) {
var c = f.geometry.coordinates;
return c[0].toFixed(5) + ', ' + c[1].toFixed(5);
}
document.getElementById('c1').textContent = fmt(centroid);
document.getElementById('c2').textContent = fmt(center);
document.getElementById('c3').textContent = fmt(mass);
document.getElementById('gap').textContent =
turf.distance(centroid, mass, { units: 'kilometers' }).toFixed(2) + ' km';
})();
</script>
</body>
</html>
Language: the code and this page are in English; the full tutorial and API notes for this example are in Chinese. The demo itself is the authoritative version — it runs exactly as shown.