Along
Sample points at fixed distances along a line and label each one.
single HTML file · CDN dependencies onlyinterface may contain Chinese labels
Source
<!--
示例:沿线取点 — 滑块控制里程,turf.along 返回线上对应位置
核心逻辑:线长由 turf.length 求出,滑块范围与线长保持一致
依赖: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:12px;align-items:center;padding:8px 12px;
background:#f6f7f9;border-bottom:1px solid #e3e6ea;font-size:12px;color:#58606e;flex-wrap:wrap}
.bar input[type=range]{width:220px}
.bar b{color:#16181d;font-weight:600}
svg{flex:1 1 auto;min-height:0;width:100%;display:block;background:#fbfcfd}
.out{flex:0 0 auto;display:flex;gap:22px;flex-wrap:wrap;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">
<label>里程 <input id="d" type="range" min="0" max="10" step="0.05" value="2"> <b id="dv">2.00 km</b></label>
<span>全长 <b id="total">—</b></span>
</div>
<svg id="stage" viewBox="0 0 640 320" preserveAspectRatio="xMidYMid meet"></svg>
<div class="out">
<span>当前点 <b id="pt">—</b></span>
<span>已行进 <span id="go">—</span></span>
<span>剩余 <span id="left">—</span></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 route = turf.lineString([
[116.300, 39.880], [116.352, 39.902], [116.418, 39.928],
[116.474, 39.912], [116.528, 39.946]
]);
var W = 640, H = 320, PAD = 46;
var stage = document.getElementById('stage');
var slider = document.getElementById('d');
var bbox = turf.bbox(route);
var kx = Math.cos(((bbox[1] + bbox[3]) / 2) * Math.PI / 180);
var x0 = bbox[0] * kx, x1 = bbox[2] * kx;
var y0 = bbox[1], y1 = bbox[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];
}
var total = turf.length(route, { units: 'kilometers' });
slider.max = total.toFixed(2);
slider.value = (total * 0.35).toFixed(2);
document.getElementById('total').textContent = total.toFixed(2) + ' km';
function draw() {
var dist = parseFloat(slider.value);
var pt = turf.along(route, dist, { units: 'kilometers' });
var parts = ['<rect x="0" y="0" width="640" height="320" fill="none" stroke="#e3e6ea"/>'];
var d = '';
route.geometry.coordinates.forEach(function (c, i) {
var p = pr(c);
d += (i ? 'L' : 'M') + p[0].toFixed(1) + ' ' + p[1].toFixed(1);
});
parts.push('<path d="' + d + '" fill="none" stroke="#1f5fd0" stroke-width="5" ' +
'stroke-linecap="round" stroke-linejoin="round" opacity="0.22"/>');
parts.push('<path d="' + d + '" fill="none" stroke="#1f5fd0" stroke-width="2" ' +
'stroke-linecap="round" stroke-linejoin="round"/>');
/* 每公里一个刻度,直观看出里程与图上间距的关系 */
for (var m = 1; m < total; m += 1) {
var tick = turf.along(route, m, { units: 'kilometers' });
var tp = pr(tick.geometry.coordinates);
parts.push('<line x1="' + (tp[0] - 3).toFixed(1) + '" y1="' + tp[1].toFixed(1) +
'" x2="' + (tp[0] + 3).toFixed(1) + '" y2="' + tp[1].toFixed(1) +
'" stroke="#8a929f" stroke-width="1"/>');
}
var p = pr(pt.geometry.coordinates);
parts.push('<line x1="' + p[0].toFixed(1) + '" y1="' + p[1].toFixed(1) +
'" x2="' + p[0].toFixed(1) + '" y2="' + (p[1] - 22).toFixed(1) +
'" stroke="#c2410c" stroke-width="1"/>');
parts.push('<circle cx="' + p[0].toFixed(1) + '" cy="' + p[1].toFixed(1) +
'" r="6" fill="#c2410c" stroke="#fff" stroke-width="2"/>');
parts.push('<text x="' + p[0].toFixed(1) + '" y="' + (p[1] - 26).toFixed(1) +
'" font-size="11" text-anchor="middle" fill="#c2410c">' +
dist.toFixed(2) + ' km</text>');
stage.innerHTML = parts.join('');
document.getElementById('dv').textContent = dist.toFixed(2) + ' km';
document.getElementById('pt').textContent =
pt.geometry.coordinates[0].toFixed(5) + ', ' +
pt.geometry.coordinates[1].toFixed(5);
document.getElementById('go').textContent = dist.toFixed(2) + ' km';
document.getElementById('left').textContent = (total - dist).toFixed(2) + ' km';
}
slider.addEventListener('input', draw);
draw();
})();
</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.