block by wboykinm 5264244

Grayscale on Watercolor

Full Screen

Ilya Zverev just posted a cool use of canvas options in Leaflet. Tileset too distracting but it’s already rendered and cached? Just make it grayscale . . .

index.html


<html>
<head>
<title>B&W TileLayer Test</title>
<link rel="stylesheet" href="https://npmcdn.com/leaflet@0.7.7/dist/leaflet.css" />
<script src="https://npmcdn.com/leaflet@0.7.7/dist/leaflet.js"></script>
<style>
body { margin: 0; }
#map { height: 100%; }
</style>
<script>
  /*
   * L.TileLayer.Grayscale is a regular tilelayer with grayscale makeover.
   */

  L.TileLayer.Grayscale = L.TileLayer.extend({
    options: {
      enableCanvas: true
    },

    initialize: function(url, options) {
      var canvasEl = document.createElement('canvas');
      if (!(canvasEl.getContext && canvasEl.getContext('2d'))) {
        options.enableCanvas = false;
      }

      L.TileLayer.prototype.initialize.call(this, url, options);
    },

    _loadTile: function(tile, tilePoint) {
      tile.setAttribute('crossorigin', 'anonymous');
      L.TileLayer.prototype._loadTile.call(this, tile, tilePoint);
    },

    _tileOnLoad: function() {
      if (this._layer.options.enableCanvas && !this.canvasContext) {
        var canvas = document.createElement("canvas");
        canvas.width = canvas.height = this._layer.options.tileSize;
        this.canvasContext = canvas.getContext("2d");
      }
      var ctx = this.canvasContext;

      if (ctx) {
        this.onload = null; // to prevent an infinite loop
        ctx.drawImage(this, 0, 0);
        var imgd = ctx.getImageData(0, 0, this._layer.options.tileSize, this._layer.options.tileSize);
        var pix = imgd.data;
        for (var i = 0, n = pix.length; i < n; i += 4) {
          pix[i] = pix[i + 1] = pix[i + 2] = (3 * pix[i] + 4 * pix[i + 1] + pix[i + 2]) / 8;
        }
        ctx.putImageData(imgd, 0, 0);
        this.removeAttribute("crossorigin");
        this.src = ctx.canvas.toDataURL();
      }

      L.TileLayer.prototype._tileOnLoad.call(this);
    }
  });

  L.tileLayer.grayscale = function(url, options) {
    return new L.TileLayer.Grayscale(url, options);
  };

  function init() {
    var map = L.map('map').setView([55.67610, 12.56834], 16);
    L.tileLayer.grayscale('//tile.stamen.com/watercolor/{z}/{x}/{y}.png', {
      attribution: 'Map data &copy; Stamen design & <a href="//openstreetmap.org/">OpenStreetMap</a> contributors',
      maxZoom: 18,
      minZoom: 2
    }).addTo(map);
  }
</script>
</head>
<body onload="javascript:init();">
<div id="map"></div>
</body>