Skip to content

Instantly share code, notes, and snippets.

@samselikoff
Last active August 29, 2015 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save samselikoff/9422682 to your computer and use it in GitHub Desktop.
Save samselikoff/9422682 to your computer and use it in GitHub Desktop.
OpenStreetMap + d3 tiles + brush slider
<html>
<meta charset="utf-8">
<style>
body {
width: 960px;
margin: 0 auto;
}
.map {
width: 100%;
height: 400px;
}
path {
fill: none;
stroke: #000;
stroke-linejoin: round;
stroke-linecap: round;
}
.major_road { stroke: #776; }
.minor_road { stroke: #ccb; }
.highway { stroke: #666; stroke-width: 1.5px; }
.rail { stroke: #999; }
.water, .ocean, .riverbank {
fill: #C7DBFF;
stroke: none;
}
.tick line {
stroke: black;
}
.tick text {
font-size: 10px;
}
</style>
<body>
<div class="map"></div>
<div class="controls"></div>
</body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/d3.geo.tile.v0.min.js"></script>
<script>
/*
Map
*/
var width = 960,
height = 500;
var tiler = d3.geo.tile()
.size([width, height]);
var center = [-71.07, 42.355];
var projection = d3.geo.mercator()
.center(center)
.scale((1 << 22) / 2 / Math.PI)
.translate([width / 2, height / 2]);
var path = d3.geo.path()
.projection(projection);
var w = d3.select('.map').style('width').replace('px',''),
h = d3.select('.map').style('height').replace('px','');
var svg = d3.selectAll('.map').append('svg')
.attr('width', w)
.attr('height', h);
svg.selectAll('g')
.data(tiler
.scale(projection.scale() * 2 * Math.PI)
.translate(projection([0, 0])))
.enter().append('g')
.each(function(d) {
var g = d3.select(this);
// d3.json('http://' + ['a', 'b', 'c'][(d[0] * 31 + d[1]) % 3] + '.tile.openstreetmap.us/vectiles-water-areas/' + d[2] + '/' + d[0] + '/' + d[1] + '.json', function(error, json) {
d3.json('http://' + ['a', 'b', 'c'][(d[0] * 31 + d[1]) % 3] + '.tile.openstreetmap.us/vectiles-all/' + d[2] + '/' + d[0] + '/' + d[1] + '.json', function(error, json) {
// Water areas
g.selectAll('path')
.data(json["water-areas"].features.sort(function(a, b) { return a.properties.sort_key - b.properties.sort_key; }))
.enter().append('path')
.attr('class', function(d) { return d.properties.kind; })
.attr('d', path);
// Highroads
g.selectAll('path')
.data(json["highroad"].features.sort(function(a, b) { return a.properties.sort_key - b.properties.sort_key; }))
.enter().append('path')
.attr('class', function(d) { return d.properties.kind; })
.attr('d', path);
});
});
// Features
d3.json('points.json', function(err, raw) {
// Add dummy data for force, angle, quality
var data = raw;
data.points.forEach(function(p) {
p.angle = Math.floor(Math.random() * 360) + 1;
p.force = Math.floor(Math.random() * 10) + 1;
p.quality = Math.floor(Math.random() * 10) + 1;
});
d3.selectAll('svg')
.selectAll('.sensor')
.data(data.points)
.enter()
.append('g')
.attr('class', function(d, i) {return 'sensor ' + i;})
.attr('transform', function(d) {return 'translate(' + projection(d.coordinates)[0] + ',' + projection(d.coordinates)[1] + ')';});
var colors = {
worst: '#fee6ce',
middle: '#fdae6b',
best: '#e6550d'
};
/*
Bubbles + slider
*/
var line = d3.svg.line(),
x = function(d) {return d.force*5 * Math.cos(d.angle * (Math.PI/180));},
y = function(d) {return d.force*5 * Math.sin(d.angle * (Math.PI/180));};
var wind = d3.selectAll('.sensor')
.append('circle')
.attr('class', 'area')
.attr('r', function(d) {return d.force * 2;})
.style('fill', function(d) {
return d.quality < 4 ? colors.worst : (d.quality < 8 ? colors.middle : colors.best);
})
.style('opacity', 0.8)
;
var parse = d3.time.format("%X %x").parse,
formatter = d3.time.format('%I %p');
var domain = ['08:00:00 03/06/2014', '18:00:00 03/06/2014'],
xScale = d3.time.scale()
.domain([parse(domain[0]), parse(domain[1])])
.range([0, 500])
.clamp(true),
xAxis = d3.svg.axis().scale(xScale)
.tickFormat(function(d) {
var t = formatter(d);
return t.charAt(0) == '0' ? t.substring(1) : t;
});
var g = d3.select('.controls').append('svg').append("g")
.attr("transform", "translate(30,40)");
g.append('g').attr('class', 'x axis').call(xAxis);
var brush = d3.svg.brush()
.x(xScale)
.extent([0, 0])
.on("brush", brushed)
;
var height = 40;
var slider = g.append("g")
.attr("class", "slider")
.attr('transform', 'translate(0,'+(-height/2)+')')
.call(brush);
slider.selectAll(".extent,.resize")
.remove();
slider.select(".background")
.attr("height", height);
var handle = slider.append("circle")
.attr("class", "handle")
.attr("transform", "translate(0," + height / 2 + ")")
.attr("r", 5);
slider.on('mousemove', function() {
var value = xScale.invert(d3.mouse(this)[0]),
nearestHour = d3.time.hour.round(value);
brush.extent([nearestHour, nearestHour]);
brushed();
});
var lastHour;
function brushed() {
var nearestHour = d3.time.hour.round(brush.extent()[0]);
brush.extent([nearestHour, nearestHour]);
if (+nearestHour !== +lastHour) {
lastHour = nearestHour;
handle.attr("cx", xScale(nearestHour));
d3.selectAll('.map circle').attr('r', function(d) {return d.force*Math.random()*4;});
}
}
});
</script>
</html>
{
"points": [
{
"coordinates": [-71.08695301055909,42.351447955911695]
},
{
"coordinates": [-71.08343395233155,42.35246284613574]
},
{
"coordinates": [-71.07905658721924,42.35360457804949]
},
{
"coordinates": [-71.07493671417237,42.35480971701297]
},
{
"coordinates": [-71.07219013214112,42.35874211499499]
},
{
"coordinates": [-71.07064517974854,42.361025329932644]
},
{
"coordinates": [-71.06798442840577,42.36660617273091]
},
{
"coordinates": [-71.06446537017823,42.3660988438709]
},
{
"coordinates": [-71.06326374053955,42.366542756847466]
},
{
"coordinates": [-71.06000217437744,42.36597201101572]
},
{
"coordinates": [-71.05768474578858,42.363625557007076]
},
{
"coordinates": [-71.05296405792237,42.36051795600514]
},
{
"coordinates": [-71.056139793396,42.36235716699952]
},
{
"coordinates": [-71.05768474578858,42.361596120703894]
},
{
"coordinates": [-71.05665477752687,42.35899580964063]
},
{
"coordinates": [-71.05948719024659,42.35931292650732]
},
{
"coordinates": [-71.0645512008667,42.352335985753925]
},
{
"coordinates": [-71.05819972991944,42.35239941597684]
},
{
"coordinates": [-71.05150493621827,42.35487314473933]
},
{
"coordinates": [-71.05193408966065,42.359439772805864]
},
{
"coordinates": [-71.05090412139893,42.36242058710804]
},
{
"coordinates": [-71.05201992034914,42.36673300430575]
},
{
"coordinates": [-71.05631145477297,42.36825496323038]
},
{
"coordinates": [-71.05819972991944,42.35220912511607]
},
{
"coordinates": [-71.05957302093506,42.35005245509584]
},
{
"coordinates": [-71.0605171585083,42.3465001313957]
},
{
"coordinates": [-71.05665477752687,42.34643669521955]
},
{
"coordinates": [-71.0619762802124,42.342884167190505]
},
{
"coordinates": [-71.06841358184815,42.347578536596444]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment