Atlaslog
Atlaslog / Examples / Leaflet / Tile Filter
Leaflet · Runnable Example

Tile Filter

Runnable Leaflet example: Tile Filter. 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 Leaflet examples
/demos/leaflet-tile-filter.htmlLIVE
single HTML file · CDN dependencies onlyinterface may contain Chinese labels

Source

demos/leaflet-tile-filter.html
<!--
  示例:瓦片滤镜
  要点:CSS filter 作用于 tilePane、五种配色、矢量层不受影响、切换类名即可生效
  依赖:Leaflet 1.9.4 · jsDelivr CDN + Esri 瓦片
-->
<!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>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.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}
  .bar{flex:0 0 auto;padding:8px 12px;background:#f6f7f9;border-bottom:1px solid #e3e6ea;
       display:flex;gap:8px;align-items:center;font-size:12px;color:#58606e;flex-wrap:wrap}
  .bar button{font:inherit;font-size:12px;padding:4px 11px;border-radius:4px;cursor:pointer;
       border:1px solid #ccd1d9;background:#fff;color:#16181d}
  .bar button:hover{background:#eef0f3}
  .bar button.is-on{background:#1f5fd0;border-color:#1f5fd0;color:#fff}
  .bar .spacer{flex:1 1 auto}
  #map{flex:1 1 auto;min-height:0}

  /* 只作用于瓦片容器,.leaflet-overlay-pane 里的矢量不受影响 */
  #map.f-gray .leaflet-tile-pane{filter:grayscale(1) contrast(1.12) brightness(1.02)}
  #map.f-night .leaflet-tile-pane{filter:invert(1) hue-rotate(180deg) brightness(.82) contrast(1.15)}
  #map.f-warm .leaflet-tile-pane{filter:sepia(.38) saturate(1.35) hue-rotate(-12deg)}
  #map.f-contrast .leaflet-tile-pane{filter:contrast(1.55) saturate(1.2)}
</style>
</head>
<body>
<div class="bar">
  <span>滤镜</span>
  <button class="fx is-on" type="button" data-fx="">原色</button>
  <button class="fx" type="button" data-fx="f-gray">灰度</button>
  <button class="fx" type="button" data-fx="f-night">夜间</button>
  <button class="fx" type="button" data-fx="f-warm">暖色</button>
  <button class="fx" type="button" data-fx="f-contrast">高对比</button>
  <span class="spacer"></span>
  <span id="status"></span>
</div>
<div id="map"></div>
<script src="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.js"></script>
<script>
(function () {
  'use strict';

  var map = L.map('map', {
    center: [39.907, 116.391],
    zoom: 12
  });

  L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}', {
    maxZoom: 19,
    attribution: 'Tiles © Esri'
  }).addTo(map);

  /* 矢量要素用来验证滤镜的边界:它们不在地图容器上,颜色保持不变 */
  L.polygon([
    [39.900, 116.370], [39.900, 116.405],
    [39.920, 116.405], [39.920, 116.370]
  ], {
    color: '#c2410c',
    weight: 3,
    fillColor: '#f97316',
    fillOpacity: 0.25
  }).addTo(map);

  L.circle([39.907359, 116.391263], {
    radius: 1100,
    color: '#1f5fd0',
    weight: 2,
    fillOpacity: 0.15
  }).addTo(map);

  L.marker([39.907359, 116.391263], {
    icon: L.divIcon({
      className: '',
      html: '<div style="width:14px;height:14px;border-radius:50%;background:#16a34a;' +
            'border:2px solid #fff;box-shadow:0 0 0 1px rgba(0,0,0,.3)"></div>',
      iconSize: [14, 14],
      iconAnchor: [7, 7]
    })
  }).bindPopup('矢量图层不受瓦片滤镜影响').addTo(map);

  var mapEl = document.getElementById('map');
  var buttons = document.querySelectorAll('.fx');
  var status = document.getElementById('status');

  var FILTERS = ['f-gray', 'f-night', 'f-warm', 'f-contrast'];

  function apply(cls, label) {
    /* 只增删滤镜类,保留 Leaflet 自身的容器类 */
    FILTERS.forEach(function (name) { mapEl.classList.remove(name); });
    if (cls) mapEl.classList.add(cls);
    status.textContent = '当前:' + label;

    for (var i = 0; i < buttons.length; i++) {
      buttons[i].classList.toggle('is-on', buttons[i].getAttribute('data-fx') === cls);
    }
  }

  for (var i = 0; i < buttons.length; i++) {
    buttons[i].addEventListener('click', function () {
      apply(this.getAttribute('data-fx'), this.textContent);
    });
  }

  status.textContent = '当前:原色';
})();
</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 Leaflet examples

Leaflet · EXAMPLETrack Playback Leaflet · EXAMPLEVideo Overlay Leaflet · EXAMPLEWMS