|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<title>d3.js with leaflet.js rendering OSM points-of-interest</title> |
|
<link rel="stylesheet" href="https://npmcdn.com/[email protected]/dist/leaflet.css"> |
|
<script src="https://npmcdn.com/[email protected]/dist/leaflet.js"></script> |
|
<script src="http://d3js.org/d3.v4.min.js"></script> |
|
</head> |
|
<body> |
|
<div id="map" style="width: 1340px; height: 635px"></div> |
|
<script type="text/javascript"> |
|
|
|
|
|
|
|
|
|
var radius = 4; |
|
var log2 = Math.log(2.0); |
|
var minZoom = 3; |
|
var maxZoom = 18; |
|
|
|
// var map = L.map('map').setView([51.53, -0.124], 14); //KGX |
|
var map = L.map('map').setView([53.96, -1.08], 14); //YRK |
|
mapLink = '<a href="http://openstreetmap.org">OpenStreetMap</a>'; |
|
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { |
|
attribution: '© ' + mapLink + ' Contributors', |
|
minZoom: minZoom, |
|
maxZoom: maxZoom |
|
}).addTo(map); |
|
L.svg().addTo(map); |
|
var svg = d3.select("#map").select("svg") |
|
, g = svg.selectAll("g"); |
|
var collections = []; |
|
var colours15 = {0: "GreenYellow", 13: "DeepSkyBlue", 3: "Gold", 5: "Red", 4: "Purple", 6: "Orange", 7: "DeepPink", 8: "Magenta", 9: "DarkSlateBlue", 10: "GreenYellow", 11: "Lime", 12: "Cyan", 1: "Blue", 14: "DarkBlue", 15: "DarkOrange", 16: "DarkOrchid"}; |
|
var colourscale = function(n) { |
|
return colours15[n]; |
|
} |
|
// mapply works for big data sets while Math.{min,max}.apply() fails |
|
function mapply(a, fn) { |
|
var m = a[0]; |
|
for (i=1; i < a.length; i++) { |
|
if (fn(a[i], m) != m) { |
|
m = a[i]; |
|
} |
|
} |
|
return m; |
|
} |
|
|
|
var arange = [25, 0]; |
|
|
|
d3.json("raildata.json", function(err, d) { |
|
if (err) |
|
return console.warn(err); |
|
d.forEach(function(v, i) { |
|
v.type = "output"; |
|
v.colour = colourscale(5); |
|
v.LatLng = new L.LatLng(v.lat,v.lon); |
|
arange[0] = Math.min(arange[0], v.lvalid); |
|
if (v.lvalid < 25) { |
|
arange[1] = Math.max(arange[1], v.lvalid); |
|
} |
|
}); |
|
collections = collections.concat(d); |
|
render(); |
|
}); |
|
|
|
function render() { |
|
var tree = d3.quadtree().x(function(d) { |
|
return d.lat; |
|
}).y(function(d) { |
|
return d.lon; |
|
}).addAll(collections); |
|
var zscale = d3.scaleLinear().domain([minZoom+1, maxZoom]).range([arange[1], arange[0]]); |
|
|
|
function visiblenodes() { |
|
var nodes = []; |
|
var z = map.getZoom(); |
|
console.log("zoom:", z, " zoomu:", zscale(z)); |
|
var bounds = map.getBounds(); |
|
var p0 = bounds._southWest |
|
, p3 = bounds._northEast; |
|
tree.visit(function(node, x1, y1, x2, y2) { |
|
if (node.data && node.data.lvalid >= zscale(map.getZoom())) { |
|
//if (node.data) { |
|
nodes.push(node.data); |
|
} |
|
return x1 >= p3.lat || y1 >= p3.lon || x2 < p0.lat || y2 < p0.lon; |
|
}); |
|
console.log("# nodes selected", nodes.length); |
|
return nodes; |
|
} |
|
map.on("viewreset", update); |
|
map.on("moveend", update); |
|
update(); |
|
|
|
function update() { |
|
g.selectAll("circle").remove(); |
|
g.selectAll("text").remove(); |
|
g.selectAll("rect").remove(); |
|
var nodes = visiblenodes() |
|
, i = 0; |
|
var feature = g.selectAll("circle").data(nodes).enter().append("g").style("fill", function(d, i) { |
|
return d.colour; |
|
}).append("svg:circle").style("stroke", "black").style("opacity", function(d, i) { |
|
return 0.6; |
|
}).attr("r", radius).attr("transform", function(d) { |
|
var p = map.latLngToLayerPoint(d.LatLng); |
|
d.x = p.x; |
|
d.y = p.y; |
|
return "translate(" + d.x + "," + d.y + ")"; |
|
}); |
|
} |
|
} |
|
|
|
</script> |
|
</body> |
|
</html> |