JSFiddle - React, Tailwind, and code Playground

by aadaam

HTML

<button id="zoomin">+</button>
<button id="zoomout">-</button>
<button id="panwest">&lt;</button>
<button id="pannorth">^</button>
<button id="pansouth">v</button>
<button id="paneast">&gt;</button>
<br>
<canvas id="mymap" width=500 height=500></canvas>

JavaScript

(function() {
    "use strict";
    //Zoomlevels on the server
    var MAX_ZOOMLEVEL = 20;

    //Size of a single tile
    var BITS_PER_TILE = 8; // 256 -> 8 bits...
    //This will be our resolution
    var NR_OF_BITS = MAX_ZOOMLEVEL + BITS_PER_TILE; // < 2^31 ? 
    var NR_OF_PIXELS_ON_LAST_ZOOMLEVEL = 1 << NR_OF_BITS; // 2^28
    //-------------
    /** @class Coordinate
     *  @abstract
     */
    var Coordinate = function() {};

    Coordinate.prototype = {
        precision: NR_OF_BITS,
        x: undefined,
        y: undefined,
        offset: function(coordinate) {
            //TODO: it's actually tricky with multiple precisions, homework... ;-)
            //Hint: What does 3 << -1 give in JS?
            var coord = new Coordinate();
            coord.x = this.x + coordinate.x;
            coord.y = this.y + coordinate.y;
            return coord;
        }
    };

    //helper function
    var beget = function(o) {
        var F = function() {};
        F.prototype = o;
        return new F();
    };

    /** @class GeoCoordinate
     * @implements Coordinate
     * A GeoCoordinate is a Coordinate in WGS-84 space, stored in max-resolution mercator.
     */
    var GeoCoordinate = function(lat, lng) {
        this.lat = lat;
        this.lng = lng;
        this.doTheMercatorMagic(lat, lng);
    };
    GeoCoordinate.prototype = beget(Coordinate.prototype);
    GeoCoordinate.prototype.precision = NR_OF_BITS;
    GeoCoordinate.prototype.doTheMercatorMagic = function(lat, lng) {
        //Flatten the Earth! Yay!
        var m = Math,
            min = m.min,
            max = m.max,
            tan = m.tan,
            PI = m.PI,
            exp = m.exp,
            log = m.log,
            round = m.round;

        this.x = round((lng / 360 + 0.5) * NR_OF_PIXELS_ON_LAST_ZOOMLEVEL);
        this.y = round(min(1, max(0, 0.5 - (log(tan(PI / 4 + PI / 2 * lat / 180)) / PI) / 2)) * NR_OF_PIXELS_ON_LAST_ZOOMLEVEL);
    };

   ...