Atlaslog
Atlaslog / Examples / Turf.js / Union
Turf.js · Runnable Example

Union

Runnable Turf.js example: Union. 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 Turf.js examples
/demos/turf-union.htmlLIVE
single HTML file · CDN dependencies onlyinterface may contain Chinese labels

Source

demos/turf-union.html
<!--
  示例:合并多边形 — turf.union 合并两个相邻面,核对面积恒等式
  核心逻辑:并集面积 = 两面面积之和 - 交集面积,用三个调用互相验证
  依赖: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 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:grid;grid-template-columns:repeat(auto-fit,minmax(170px,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>实线为原面轮廓,绿色填充为合并结果</span>
</div>
<svg id="stage" viewBox="0 0 640 320" preserveAspectRatio="xMidYMid meet"></svg>
<div class="out">
  <span>并集面积 <b id="u">—</b></span>
  <span>两面之和 <span id="sum">—</span></span>
  <span>重叠面积 <span id="ov">—</span></span>
  <span>结果类型 <b id="type">—</b></span>
  <span>顶点数 <span id="n">—</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 west = turf.polygon([[
    [116.300, 39.880], [116.420, 39.880], [116.420, 39.960],
    [116.300, 39.960], [116.300, 39.880]
  ]], { name: '西区' });

  var east = turf.polygon([[
    [116.380, 39.900], [116.500, 39.900], [116.500, 39.980],
    [116.380, 39.980], [116.380, 39.900]
  ]], { name: '东区' });

  var W = 640, H = 320, PAD = 35;
  var BOX = [116.27, 39.855, 116.53, 40.005];
  var stage = document.getElementById('stage');

  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 merged = turf.union(west, east);
  var parts = ['<rect x="0" y="0" width="640" height="320" fill="none" stroke="#e3e6ea"/>'];

  var polys = merged.geometry.type === 'MultiPolygon'
    ? merged.geometry.coordinates
    : [merged.geometry.coordinates];

  polys.forEach(function (poly) {
    poly.forEach(function (ring, i) {
      parts.push('<path d="' + ringPath(ring) +
                 '" fill="' + (i === 0 ? 'rgba(23,105,74,0.22)' : '#fbfcfd') +
                 '" fill-rule="evenodd" stroke="#17694a" stroke-width="2"/>');
    });
  });

  parts.push('<path d="' + ringPath(west.geometry.coordinates[0]) +
             '" fill="none" stroke="#1f5fd0" stroke-width="1.5" stroke-dasharray="6 4"/>');
  parts.push('<path d="' + ringPath(east.geometry.coordinates[0]) +
             '" fill="none" stroke="#c2410c" stroke-width="1.5" stroke-dasharray="6 4"/>');

  stage.innerHTML = parts.join('');

  var u = turf.area(merged);
  var sum = turf.area(west) + turf.area(east);

  document.getElementById('u').textContent = (u / 1e6).toFixed(2) + ' km²';
  document.getElementById('sum').textContent = (sum / 1e6).toFixed(2) + ' km²';
  document.getElementById('ov').textContent = ((sum - u) / 1e6).toFixed(2) + ' km²';
  document.getElementById('type').textContent = merged.geometry.type;
  document.getElementById('n').textContent =
    merged.geometry.type === 'MultiPolygon'
      ? polys.reduce(function (acc, p) { return acc + p[0].length; }, 0)
      : polys[0][0].length;
})();
</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 Turf.js examples

Turf.js · EXAMPLEAlong Turf.js · EXAMPLEArea Turf.js · EXAMPLEArea Compare