-
-
Save xEviL/23c785a48f4dbe9a9957052e7a82d369 to your computer and use it in GitHub Desktop.
New York City Sample Bike Path (D3)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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:1}); | |
L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', { | |
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> © <a href="http://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", | |
"shape-rendering": "crispEdges" | |
}); | |
sel.attr("stroke-width", 1 / proj.scale); | |
} | |
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> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Copyright 2015 Teralytics AG | |
* | |
* @author Kirill Zhuravlev <[email protected]> | |
* | |
*/ | |
(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); | |
}; | |
})); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[[[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]]] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment