Chaikin
Runnable OpenLayers example: Chaikin. 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
<!--
示例:Chaikin 曲线平滑
要点:对折线顶点反复取 1/4、3/4 分割点,得到更顺滑的线形
依赖:OpenLayers 10.3.1 · 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>Chaikin 曲线平滑</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@10.3.1/ol.css">
<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}
.bar{flex:0 0 auto;padding:8px 12px;background:#f6f7f9;border-bottom:1px solid #e3e6ea;
display:flex;gap:12px;align-items:center;font-size:12px;color:#58606e}
.bar input[type=range]{width:140px}
#map{flex:1 1 auto;min-height:0;background:#eef0f3}
</style>
</head>
<body>
<div class="bar">
<label for="ite">平滑次数 <b id="itev">1</b></label>
<input type="range" id="ite" min="0" max="5" value="1" step="1">
<span id="count">原始顶点 12 个</span>
</div>
<div id="map"></div>
<script src="https://cdn.jsdelivr.net/npm/ol@10.3.1/dist/ol.js"></script>
<script>
(function () {
'use strict';
if (!window.ol) {
document.getElementById('map').textContent = 'OpenLayers 加载失败,请检查 cdn.jsdelivr.net 是否可访问';
return;
}
var fromLonLat = ol.proj.fromLonLat;
/* 一条带折角的路线,经纬度给出 */
var lonlat = [
[116.30, 39.90], [116.33, 39.945], [116.36, 39.905], [116.395, 39.96],
[116.43, 39.915], [116.465, 39.965], [116.50, 39.92], [116.52, 39.87],
[116.47, 39.845], [116.415, 39.875], [116.365, 39.845], [116.315, 39.865]
];
var base = lonlat.map(function (p) { return fromLonLat(p); });
/* Chaikin:每个线段取 25% 与 75% 两点,端点保留 */
function chaikin(pts, iterations) {
var out = pts.slice();
for (var n = 0; n < iterations; n++) {
var next = [out[0]];
for (var i = 0; i < out.length - 1; i++) {
var p0 = out[i], p1 = out[i + 1];
next.push([p0[0] * 0.75 + p1[0] * 0.25, p0[1] * 0.75 + p1[1] * 0.25]);
next.push([p0[0] * 0.25 + p1[0] * 0.75, p0[1] * 0.25 + p1[1] * 0.75]);
}
next.push(out[out.length - 1]);
out = next;
}
return out;
}
var rawLine = new ol.Feature({ geometry: new ol.geom.LineString(base) });
var smoothLine = new ol.Feature({ geometry: new ol.geom.LineString(base) });
rawLine.setStyle(new ol.style.Style({
stroke: new ol.style.Stroke({ color: 'rgba(180,35,24,0.7)', width: 1.5, lineDash: [6, 4] })
}));
smoothLine.setStyle(new ol.style.Style({
stroke: new ol.style.Stroke({ color: '#1f5fd0', width: 3 })
}));
var vertices = new ol.source.Vector({
features: base.map(function (c) {
return new ol.Feature({
geometry: new ol.geom.Point(c),
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 3,
fill: new ol.style.Fill({ color: '#b42318' })
})
})
});
})
});
var layer = new ol.layer.Vector({
source: new ol.source.Vector({ features: [rawLine, smoothLine] })
});
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({ source: new ol.source.XYZ({url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}', attributions: 'Tiles © Esri'}) }),
layer,
new ol.layer.Vector({ source: vertices })
],
view: new ol.View({ center: fromLonLat([116.41, 39.91]), zoom: 12 }),
controls: ol.control.defaults.defaults({ rotate: false })
});
function apply(n) {
var pts = chaikin(base, n);
smoothLine.getGeometry().setCoordinates(pts);
document.getElementById('itev').textContent = n;
document.getElementById('count').textContent = '平滑后顶点 ' + pts.length + ' 个';
}
document.getElementById('ite').addEventListener('input', function () {
apply(Number(this.value));
});
apply(1);
})();
</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.