Atlaslog
Atlaslog / Examples / OpenLayers / Chaikin
OpenLayers · Runnable Example

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.

Open standalone → Chinese notes All OpenLayers examples
/demos/openlayers-chaikin.htmlLIVE
single HTML file · CDN dependencies onlyinterface may contain Chinese labels

Source

demos/openlayers-chaikin.html
<!--
  示例: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.

More OpenLayers examples

OpenLayers · EXAMPLECluster OpenLayers · EXAMPLECluster Graded OpenLayers · EXAMPLEClusters Dynamic