Exploring procedural maps with leaflet

Just a Perlin-made island computed on-the-fly with leaflet! Code:

<!DOCTYPE html>
<html>
<head>
    
    <title>Exploring Perlin Noise With Leaflet</title>

    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="shortcut icon" type="image/x-icon" href="docs/images/favicon.ico" />
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.2/dist/leaflet.css" />
    <script src="https://unpkg.com/leaflet@1.0.2/dist/leaflet.js"></script>
    <!-- Perlin code from josephg: https://github.com/josephg/noisejs -->
    <script src='perlin.js'></script>

    <style>
        #map {
            width: 512px;
            height: 256px;
        }
    </style>

</head>
<body>

<div id='map'></div>

<script>

    // RGB and scale values for the color palette
    var cRed   = [0,0.7,0.2,0.1333,0.2,0.35,0.7,0.7,1,1];
    var cGreen = [0.1,0.6,0.3,0.2,0.3,0.3,0.6,0.6,1,1];
    var cBlue  = [0.24,0.4,0.1,0.0666,0.1,0.2,0.4,0.4,1,1];
    var w      = [0.,1e-6,1e-4,1e-3,0.1,0.3,0.8,0.9,1,10];
            
    // Seed for noise
    noise.seed(300); //[1,65536]
    var k=8 // resolution ( k: [0,8] per tile )
    
    var map = L.map('map', {
        center: [0, 0],
        zoom: 0
    });

    L.GridLayer.CanvasCircles = L.GridLayer.extend({
        createTile: function (coords) {
            var tile = document.createElement('canvas');
            
            var tileSize = this.getTileSize();
            tile.setAttribute('width', tileSize.x);
            tile.setAttribute('height', tileSize.y);
        
            var ctx = tile.getContext('2d');
            
            // Draw whatever is needed in the canvas context
            // Loop for every 'pixel' in the tile
            for (var i = 0; i < Math.pow(2,k); ++i) {
            for (var j = 0; j < Math.pow(2,k); ++j) {

                // (x,y) absolute coordinates from local ones
                xx = ( coords.x/Math.pow(2,coords.z)+i/Math.pow(2,k)/Math.pow(2,coords.z) );
                yy = ( coords.y/Math.pow(2,coords.z)+j/Math.pow(2,k)/Math.pow(2,coords.z) );
                
                // Some Perlin octaves
                var sum = 0;
                for(var kk=0; kk <= 10; kk+=2 ) {
                    q = Math.pow(2,kk);
                    sum +=  (noise.perlin2( xx*q, yy*q)+1)/2/Math.sqrt(q);
                }
                // Perlin plus some extra elevation for making an island (arbitrary)
                value = ( (noise.perlin2(xx,yy)+1)/2 + sum ) + 0.25*Math.sin(xx*Math.PI)*Math.sin(yy*Math.PI);
                // Delimiting range
                value = Math.pow(Math.abs(Math.max(1.85,value)-1.85),3)*27;

                // Asigning colors
                kk = 0;
                while( value >= w[kk] ) {kk++;}
                kk--;
                rr = (value-w[kk])/(w[kk+1]-w[kk])*(cRed[kk+1]  -cRed[kk]  )+cRed[kk];
                gg = (value-w[kk])/(w[kk+1]-w[kk])*(cGreen[kk+1]-cGreen[kk])+cGreen[kk];
                bb = (value-w[kk])/(w[kk+1]-w[kk])*(cBlue[kk+1] -cBlue[kk] ) +cBlue[kk];
                ctx.fillStyle=writeColor3(255*rr,255*gg,255*bb);
                
                // Put the pixel
                ctx.fillRect(i*Math.pow(2,8-k), j*Math.pow(2,8-k),Math.pow(2,8-k),Math.pow(2,8-k));

            }}
            
            return tile;
        }
    });
    
    L.gridLayer.canvasCircles = function(opts) {
        return new L.GridLayer.CanvasCircles(opts);
    };

    map.addLayer( L.gridLayer.canvasCircles() );
    
    //my color
    function writeColor3(r1,r2,r3) { // RGB from 0 to 255. It returns color in Hex
        var a = (Math.round(r1)).toString(16);
        var b = (Math.round(r2)).toString(16);
        var c = (Math.round(r3)).toString(16);
        if (a.length == 1) {a = "0"+a;}
        if (b.length == 1) {b = "0"+b;}
        if (c.length == 1) {c = "0"+c;}
        return "#"+a+b+c;
    }
    
</script>

</body>
</html>