block by ResidentMario 13e902fd16fca628cc3fc826600bd2fe

New York City Sample Bike Path (D3)

Full Screen

index.html

<!DOCTYPE html>
<html>
<head>
    <title>A Week in the Life of a CitiBike</title>

    <style type="text/css">
        html { height: 100% }
        body { height: 100%; margin: 0; padding: 0 }
        #map-canvas { height: 100% }
    </style>
    <link href='https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/leaflet.css'
    	rel='stylesheet' type='text/css'/>
    <meta http-equiv="X-UA-Compatible" content="IE=Edge">
</head>
<body>
    <div id="map-canvas"></div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/leaflet.js"></script>
    <script src="https://d3js.org/d3.v3.js"></script>
    <script src="https://d3js.org/d3-queue.v3.js"></script>
    <script src="L.D3SvgOverlay.js"></script>
    <script>

        // Initializes the basemap.
        var map = L.map("map-canvas",{center:[40.773889, -73.983611],zoom:12});
        L.tileLayer('//{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {
            attribution: '&copy; <a href="//www.openstreetmap.org/copyright">OpenStreetMap</a> &copy; <a href="//cartodb.com/attributions">CartoDB</a>',
            subdomains: 'abcd',
            maxZoom: 19
        }).addTo(map);

        // D3-SVG-Overlay callback wrapper. Leaflet is used only for the base map, all of the programmatic action occurs
        // in d3 code inside of this callback.
        var mapOverlay = L.d3SvgOverlay(function(sel,proj){

            // Paints a single sampler path.
            function paintPath(linearray) {
                console.log(linearray);

                // Define x and y conversions.
                var line = d3.svg.line()
                        .x(function(d) { console.log(d); return proj.latLngToLayerPoint(d).x})
                        .y(function(d) { console.log(d); return proj.latLngToLayerPoint(d).y});

                console.log(line);

                sel.append("path")
                        .datum(linearray)
                        .attr({
                            "class": "sample-line",
                            "d": line,
                            "fill": "transparent",
                            "stroke": "steelblue",
                            "stroke-width": 0.1,
                            "shape-rendering": "crispEdges"
                        })
            }

            function paintPathSampler() {
                d3.json("path_sampler.json", function (data) {
                    console.log(data[0]);

                    paintPath(data[0]);
                    paintPath(data[1]);
                });
            }

            paintPathSampler();
         });

        // Add overlay to map.
        mapOverlay.addTo(map);
    </script>
</body>
</html>

L.D3SvgOverlay.js

/**
 * Copyright 2015 Teralytics AG
 *
 * @author Kirill Zhuravlev <kirill.zhuravlev@teralytics.ch>
 *
 */

(function (factory) {
   if (typeof define === 'function' && define.amd) {
       define(['leaflet', 'd3'], factory);
   } else if (typeof module === 'object' && module.exports) {
       module.exports = factory(require('leaflet', 'd3'));
   } else {
       factory(L, d3);
   }
}(function (L, d3) {

// Check requirements
if (typeof d3 == "undefined") {
    throw "D3 SVG Overlay for Leaflet requires D3 library loaded first";
}
if (typeof L == "undefined") {
    throw "D3 SVG Overlay for Leaflet requires Leaflet library loaded first";
}

// Tiny stylesheet bundled here instead of a separate file
if (L.version >= "1.0") {
    d3.select("head")
        .append("style").attr("type", "text/css")
        .text("g.d3-overlay *{pointer-events:visiblePainted;}");
}

// Class definition
L.D3SvgOverlay = (L.version < "1.0" ? L.Class : L.Layer).extend({
    includes: (L.version < "1.0" ? L.Mixin.Events : []),

    _undef: function(a){ return typeof a == "undefined" },

    _options: function (options) {
        if (this._undef(options)) {
            return this.options;
        }
        options.zoomHide = this._undef(options.zoomHide) ? false : options.zoomHide;
        options.zoomDraw = this._undef(options.zoomDraw) ? true : options.zoomDraw;

        return this.options = options;
    },

    _disableLeafletRounding: function(){
        this._leaflet_round = L.Point.prototype._round;
        L.Point.prototype._round = function(){ return this; };
    },

    _enableLeafletRounding: function(){
        L.Point.prototype._round = this._leaflet_round;
    },

    draw: function () {
        this._disableLeafletRounding();
        this._drawCallback(this.selection, this.projection, this.map.getZoom());
        this._enableLeafletRounding();
    },

    initialize: function (drawCallback, options) { // (Function(selection, projection)), (Object)options
        this._options(options || {});
        this._drawCallback = drawCallback;
    },

    // Handler for "viewreset"-like events, updates scale and shift after the animation
    _zoomChange: function (evt) {
        this._disableLeafletRounding();
        var newZoom = this._undef(evt.zoom) ? this.map._zoom : evt.zoom; // "viewreset" event in Leaflet has not zoom/center parameters like zoomanim
        this._zoomDiff = newZoom - this._zoom;
        this._scale = Math.pow(2, this._zoomDiff);
        this.projection.scale = this._scale;
        this._shift = this.map.latLngToLayerPoint(this._wgsOrigin)
            ._subtract(this._wgsInitialShift.multiplyBy(this._scale));

        var shift = ["translate(", this._shift.x, ",", this._shift.y, ") "];
        var scale = ["scale(", this._scale, ",", this._scale,") "];
        this._rootGroup.attr("transform", shift.concat(scale).join(""));

        if (this.options.zoomDraw) { this.draw() }
        this._enableLeafletRounding();
    },

    onAdd: function (map) {
        this.map = map;
        var _layer = this;

        // SVG element
        if (L.version < "1.0") {
            map._initPathRoot();
            this._svg = d3.select(map._panes.overlayPane)
                .select("svg");
            this._rootGroup = this._svg.append("g");
        } else {
            this._svg = L.svg();
            map.addLayer(this._svg);
            this._rootGroup = d3.select(this._svg._rootGroup).classed("d3-overlay", true);
        }
        this._rootGroup.classed("leaflet-zoom-hide", this.options.zoomHide);
        this.selection = this._rootGroup;

        // Init shift/scale invariance helper values
        this._pixelOrigin = map.getPixelOrigin();
        this._wgsOrigin = L.latLng([0, 0]);
        this._wgsInitialShift = this.map.latLngToLayerPoint(this._wgsOrigin);
        this._zoom = this.map.getZoom();
        this._shift = L.point(0, 0);
        this._scale = 1;

        // Create projection object
        this.projection = {
            latLngToLayerPoint: function (latLng, zoom) {
                zoom = _layer._undef(zoom) ? _layer._zoom : zoom;
                var projectedPoint = _layer.map.project(L.latLng(latLng), zoom)._round();
                return projectedPoint._subtract(_layer._pixelOrigin);
            },
            layerPointToLatLng: function (point, zoom) {
                zoom = _layer._undef(zoom) ? _layer._zoom : zoom;
                var projectedPoint = L.point(point).add(_layer._pixelOrigin);
                return _layer.map.unproject(projectedPoint, zoom);
            },
            unitsPerMeter: 256 * Math.pow(2, _layer._zoom) / 40075017,
            map: _layer.map,
            layer: _layer,
            scale: 1
        };
        this.projection._projectPoint = function(x, y) {
            var point = _layer.projection.latLngToLayerPoint(new L.LatLng(y, x));
            this.stream.point(point.x, point.y);
        };
        this.projection.pathFromGeojson =
            d3.geo.path().projection(d3.geo.transform({point: this.projection._projectPoint}));

        // Compatibility with v.1
        this.projection.latLngToLayerFloatPoint = this.projection.latLngToLayerPoint;
        this.projection.getZoom = this.map.getZoom.bind(this.map);
        this.projection.getBounds = this.map.getBounds.bind(this.map);
        this.selection = this._rootGroup;

        if (L.version < "1.0") map.on("viewreset", this._zoomChange, this);

        // Initial draw
        this.draw();
    },

    // Leaflet 1.0
    getEvents: function() { return {zoomend: this._zoomChange}; },

    onRemove: function (map) {
        if (L.version < "1.0") {
            map.off("viewreset", this._zoomChange, this);
            this._rootGroup.remove();
        } else {
            this._svg.remove();
        }
    },

    addTo: function (map) {
        map.addLayer(this);
        return this;
    }

});

L.D3SvgOverlay.version = "2.2";

// Factory method
L.d3SvgOverlay = function (drawCallback, options) {
    return new L.D3SvgOverlay(drawCallback, options);
};

}));

path_sampler.json

[[[40.76529, -73.98208], [40.76476, -73.98225], [40.76457, -73.98232], [40.76441, -73.98238], [40.76438, -73.98239], [40.76434, -73.98241], [40.76423, -73.98245], [40.76412, -73.98249], [40.76405, -73.98252], [40.76402, -73.98254], [40.76396, -73.98257], [40.76351, -73.98281], [40.76339, -73.98288], [40.7633, -73.98293], [40.76318, -73.983], [40.76282, -73.98321], [40.76273, -73.98326], [40.76264, -73.98332], [40.76219, -73.9836], [40.76207, -73.98368], [40.76178, -73.98387], [40.76145, -73.98411], [40.7608, -73.98452], [40.76072, -73.98456], [40.76052, -73.98465], [40.76013, -73.98487], [40.76013, -73.98487], [40.75999, -73.98453], [40.75984, -73.98418], [40.75984, -73.98418], [40.75952, -73.98441], [40.7592, -73.98461], [40.75858, -73.98507], [40.75833, -73.98526], [40.75796, -73.98553], [40.75778, -73.98568], [40.75734, -73.986], [40.7567, -73.98648], [40.75603, -73.98695], [40.75603, -73.98695], [40.75582, -73.98644], [40.75582, -73.98644], [40.75505, -73.98668], [40.75434, -73.98691], [40.75362, -73.98713], [40.75332, -73.98723], [40.75303, -73.98732], [40.75291, -73.98735], [40.75218, -73.98754], [40.75187, -73.98761], [40.75183, -73.98762], [40.75145, -73.98771], [40.7512, -73.98774], [40.7507, -73.98783], [40.75036, -73.98789], [40.74988, -73.98798], [40.74968, -73.98804], [40.74957, -73.98809], [40.74948, -73.98814], [40.74925, -73.9883], [40.74924, -73.9883], [40.74923, -73.98829], [40.74919, -73.98819], [40.74912, -73.98804], [40.74912, -73.98802], [40.74911, -73.98802], [40.7491, -73.98801], [40.749, -73.98803], [40.74898, -73.98805], [40.74896, -73.98807], [40.74894, -73.98808], [40.74881, -73.9881], [40.74869, -73.98812], [40.74863, -73.98813], [40.74858, -73.98814], [40.74845, -73.98817], [40.74831, -73.9882], [40.74811, -73.98824], [40.74754, -73.98836], [40.74735, -73.98839], [40.74721, -73.98841], [40.74713, -73.98843], [40.74707, -73.98844], [40.74679, -73.98849], [40.74604, -73.98858], [40.74582, -73.98867], [40.74559, -73.98872], [40.7453, -73.98877], [40.74455, -73.9889], [40.74435, -73.98894], [40.74412, -73.98899], [40.74392, -73.98903], [40.7438, -73.98904], [40.74368, -73.98905], [40.74337, -73.98911], [40.74316, -73.98915], [40.74303, -73.98917], [40.74294, -73.98919], [40.74261, -73.98924], [40.74257, -73.98924], [40.74253, -73.98924], [40.74252, -73.98923], [40.7425, -73.98922], [40.74231, -73.98902], [40.74231, -73.98902], [40.74225, -73.98906], [40.7419, -73.98931], [40.7418, -73.9894], [40.74155, -73.98959], [40.74087, -73.9901], [40.74025, -73.99053], [40.73967, -73.99096], [40.73908, -73.99139], [40.73849, -73.99181], [40.73792, -73.99222], [40.73732, -73.99267], [40.73669, -73.99315], [40.73624, -73.99347], [40.73618, -73.99352], [40.73602, -73.99363], [40.7353, -73.99416], [40.73467, -73.99459], [40.73403, -73.99507], [40.73344, -73.99552], [40.73284, -73.99594], [40.73225, -73.99638], [40.73185, -73.99668], [40.73141, -73.99698], [40.73141, -73.99698], [40.73147, -73.9971], [40.73216, -73.9985], [40.73222, -73.99863], [40.73222, -73.99863], [40.73211, -73.99873], [40.73164, -73.99913], [40.73105, -73.99962], [40.73105, -73.99962], [40.73067, -73.99886], [40.73067, -73.99886], [40.73046, -73.99903]]]