Skip to content

Instantly share code, notes, and snippets.

@vigorousnorth
Last active August 29, 2015 13:57
Show Gist options
  • Select an option

  • Save vigorousnorth/9370888 to your computer and use it in GitHub Desktop.

Select an option

Save vigorousnorth/9370888 to your computer and use it in GitHub Desktop.
D3 weather map

D3 weather map

A basic map of weather data displayed as text annotations in D3.

var temps = {};
// Define historic climate data
temps = {
'Bangor' :
{
thiswinter_low: -20, thiswinter_lowdate: 'Jan. 4',
record_low: -32, record_lowdate: 'Feb. 2, 1948', record_lowsince: 1925
},
'Caribou' :
{
thiswinter_low: -28, thiswinter_lowdate: 'Jan. 2',
record_low: -41, record_lowdate: 'Feb. 1, 1955', record_lowsince: 1939
},
'Presque Isle':
{
thiswinter_low: -29, thiswinter_lowdate: 'Jan. 2, Jan. 4',
record_low: -41, record_lowdate: 'Jan. 19, 1925', record_lowsince: 1893
},
'Houlton' :
{
thiswinter_low: -24, thiswinter_lowdate: 'Jan. 2',
record_low: -41, record_lowdate: 'Jan. 4, 1981', record_lowsince: 1948
},
'Millinocket' :
{
thiswinter_low: -16, thiswinter_lowdate: 'Jan. 1, Jan. 2',
record_low: -40, record_lowdate: 'Feb. 2, 1962', record_lowsince: 1944
},
'Waterville' :
{
thiswinter_low: -18, thiswinter_lowdate: 'Jan. 4', record_low: -39, record_lowdate: 'Dec. 30, 1933', record_lowsince: 1896
},
'Bar Harbor' :
{
thiswinter_low: -9, thiswinter_lowdate: 'Jan. 4'
} ,
'Sanford' :
{
thiswinter_low: -22, thiswinter_lowdate: 'Jan. 4'
} ,
'Portland' :
{
thiswinter_low: -14, thiswinter_lowdate: 'Jan. 4',
record_low: -39, record_lowdate: 'Feb. 16, 1943', record_lowsince: 1874
},
'Augusta' :
{
thiswinter_low: -13, thiswinter_lowdate: 'Jan. 4', record_low: -23, record_lowdate: 'Feb. 2, 1962', record_lowsince: 1948
},
'Auburn' :
{
thiswinter_low: -18, thiswinter_lowdate: 'Jan. 4'
}
};
// Definte current temperature data (can be pulled via a php script from weather.gov)
temps['Sanford'].currenttemp = 11 ;
temps['Portland'].currenttemp = 10 ;
temps['Augusta'].currenttemp = -2 ;
temps['Bar Harbor'].currenttemp = 12 ;
temps['Auburn'].currenttemp = 1 ;
temps['Waterville'].currenttemp = -15 ;
temps['Millinocket'].currenttemp = -10 ;
temps['Houlton'].currenttemp = -3 ;
temps['Caribou'].currenttemp = -20 ;
temps['Presque Isle'].currenttemp = -9 ;
temps['Bangor'].currenttemp = -19 ;
$(document).ready(function() {
// Build the map
var width = 700,
height = 800;
var projection = d3.geo.conicConformal()
.parallels([38 + 02 / 60, 39 + 12 / 60])
.rotate([70, 0])
.scale(8500)
.translate([0.4*width, 9.5*height]);
var path = d3.geo.path()
.projection(projection)
.pointRadius(30);
var svg = d3.select("#mainmap").append("svg")
.attr("width", width)
.attr("height", height);
var g = svg.append("g");
var colorrange = d3.scale.linear()
.domain([-30, 50])
.range(["rgb(0,191,255)", "rgb(255,0,0)"]);
d3.json("mainecitiesandcounties_topo.json", function(error, topo) {
// Append temperature data to data object
for (city in temps) {
for (var i=0,len=topo.objects.cities.geometries.length; i<len; i++) {
if (topo.objects.cities.geometries[i]['properties']['name'] === city) {
topo.objects.cities.geometries[i]['properties']['temps'] = temps[city]
}
}
}
var counties = g.append("g")
.attr("class", "counties")
.selectAll("path")
.data(topojson.feature(topo, topo.objects.counties).features)
.enter().append("path")
.attr("d", path);
var cities =
g.append("g")
.selectAll("path")
.data(topojson.feature(topo, topo.objects.cities).features)
.enter().append("path")
.attr("class", "place")
.attr("d", path)
.attr("centroid-x", function(d) {
var centroid = path.centroid(d);
return centroid[0];
} )
.attr("centroid-y", function(d) {
var centroid = path.centroid(d);
return centroid[1];
});
var citylabels =
g.append("g").selectAll(".currenttemperature-label")
.data(topojson.feature(topo, topo.objects.cities).features)
.enter().append("text")
.attr("class", "currenttemperature-label")
.attr("transform", function(d) { return "translate(" + projection(d.geometry.coordinates) + ")"; })
.attr("dy", ".35em")
.attr("dx", "-.5em")
.text(function(d) {
if (d.properties.temps) return d.properties.temps.currenttemp;
})
.style("fill", function(d) {
if (d.properties.temps) return colorrange(d.properties.temps.currenttemp);
})
.on("mouseover", function(d) {
$('.currenttemperature-label').not(this).animate({opacity:0.1},200);
var s = d.properties.name;
var id = "#" + s.split(' ');
console.log(id);
$(id).fadeIn(500);
})
.on("mouseout", function(d) {
$('.currenttemperature-label').animate({opacity:1},100);
var s = d.properties.name;
var id = "#" + s.split(' ');
$(id).fadeOut(500);
});
var annotations =
g.append("g").selectAll(".more")
.data(topojson.feature(topo, topo.objects.cities).features)
.enter().append("text")
.text(function(d) {
return d.properties.name;
})
.attr("class", "more")
.attr("id", function(d) {
var s = d.properties.name;
return s.split(" ")[0];
})
.attr("transform", function(d) { return "translate(" + projection(d.geometry.coordinates) + ")"; })
.attr("dy", "2em")
.attr("dx", "-.5em");
annotations.append('tspan')
.text(function(d) {
if (d.properties.temps && d.properties.temps.thiswinter_low) {
return ("This winter's record low: ");
}
})
.attr("x","-.5em").attr("dy","1em")
.append('tspan').text(function(d) {
if (d.properties.temps && d.properties.temps.thiswinter_low) {
return d.properties.temps.thiswinter_low;
}
})
.attr('class','number')
.style("fill", function(d) {
if (d.properties.temps && d.properties.temps.thiswinter_low) {
return colorrange(d.properties.temps.thiswinter_low);
}
});
annotations.append("tspan").text(function(d) {
if (d.properties.temps && d.properties.temps.thiswinter_low) {
return "on " + d.properties.temps.thiswinter_lowdate;
}
}).attr("x","-.5em").attr("dy","1em");
annotations.append("tspan").text(function(d) {
if (d.properties.temps && d.properties.temps.record_low) {
return "Record low (since " + d.properties.temps.record_lowsince + "): ";
}
}).attr("x","-.5em").attr("dy","1.1em")
.append('tspan').text(function(d) {
if (d.properties.temps && d.properties.temps.record_low) {
return d.properties.temps.record_low;
}
})
.attr('class','number')
.style("fill", function(d) {
if (d.properties.temps && d.properties.temps.record_low) { return colorrange(d.properties.temps.record_low); }
});
annotations.append("tspan").text(function(d) {
if (d.properties.temps && d.properties.temps.record_low) {
return "on " + d.properties.temps.record_lowdate;
}
})
.attr("x","-.5em").attr("dy","1em")
});
});
<!DOCTYPE html>
<meta charset="utf-8">
<head>
<link href='http://fonts.googleapis.com/css?family=Open+Sans+Condensed:300' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,600,800' rel='stylesheet' type='text/css'>
<link href='style.css' rel='stylesheet' type='text/css'>
<script src="http://d3js.org/d3.v3.js"></script>
<script src="http://d3js.org/d3.geo.projection.v0.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="d3weathermap.js"></script>
</head>
<body>
<div id="coldtracchatter">
<h1>Current temperatures</h1>
<p>Mouse over the map's temperature readings to compare record lows for each location.</p>
</div>
<div id="mainmap">
</div>
</body>
</html>
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
<style type='text/css'>
body {width: 680px}
path {
stroke-linejoin: round;
stroke-linecap: round;
}
#mainmap {position: relative;}
#mainmap .state {
fill: #eee;
stroke: #222;
stroke-width: 2px;
}
#mainmap .counties {
fill: rgb(245,245,245);
stroke: #000;
stroke-width: 0.25px;
stroke-linejoin: round;
stroke-linecap: round;
}
#mainmap .active {
stroke: #eee; stroke-width: 0.5px;
}
#mainmap .currenttemperature-label {
font-family: "Open Sans", sans-serif;
font-weight: 800;
z-index: 1000;
color: #222;
font-size: 2.2em;
}
#mainmap .more {
font-family: "Open Sans", sans-serif;
font-weight: 400;
z-index: 1000;
color: #222;
font-size: 1em;
display: none;
}
#mainmap .more tspan {
font-size: 0.9em;
}
#mainmap tspan .number {
font-weight: 800;
font-size: 1em;
}
#mainmap .place { fill: none; stroke: none; }
#mainmap .label {font-family: 'Open Sans',sans-serif; float: right; width: 450px}
h1, h2 {font-family: 'Open Sans',sans-serif; }
#coldtracchatter {
font-family: 'Open Sans',sans-serif;
position: absolute;
left: 10px;
top: 40px;
width: 380px;
z-index: 100;
}
#coldtracchatter p {
width: 230px;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment