Skip to content

Instantly share code, notes, and snippets.

@dcposch
Created November 27, 2012 08:01
Show Gist options
  • Save dcposch/4153053 to your computer and use it in GitHub Desktop.
Save dcposch/4153053 to your computer and use it in GitHub Desktop.
D3GL Earth Climate

Earth's climate.

Drag to rotate, mousewheel to zoom. Click a play/pause to animate. Click a country for details.

Built with d3gl

<!DOCTYPE html>
<html>
<head>
<title>D3GL Earth Climate</title>
<link rel="stylesheet" href="http://dcpos.ch/d3gl/css/demo.css" />
<link rel="stylesheet" href="http://dcpos.ch/d3gl/css/demo-countries.css" />
</head>
<body>
<ul id="picker">
</ul>
<div id="climate-globe-labels">
<div id="pr">
Precipitation <br />
<img src="http://dcpos.ch/d3gl/demos/pr_scale.png" />
</div>
<div id="tas">
Temperature <br />
<img src="http://dcpos.ch/d3gl/demos/tas_scale.png" />
</div>
</div>
<script type="text/javascript" src="http://dcpos.ch/d3gl/js/d3gl.min.js"></script>
<script type="text/javascript" src="http://dcpos.ch/d3gl/data/country_code_map.js"></script>
<script type="text/javascript">
var climateDataTypes = ["pr", "tas"];
var months = ["Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sep", "Oct", "Nov", "Dec"];
var monthIdx = 0; // jan displays by default
function createControls(){
var selected, hovered, active, playing = false;
d3.select("#picker").selectAll("li")
.data(months)
.enter().append("li")
.text(function(d){ return d; })
.attr("id", function(d, i) {
return d;
})
.on('mouseover', function(d) {
if(hovered) $(hovered).removeClass("hovered");
$(hovered = this).addClass("hovered");
})
.on('mouseout', function(d) {
$(this).removeClass("hovered");
hovered = null;
})
.on('mousedown', function(d) {
if(active) $(active).removeClass("active");
$(active = this).addClass("active");
})
.on('mouseup', function(d) {
$(this).removeClass("active");
})
.on('click', function(d) {
if(selected) $(selected).removeClass("selected");
$(selected = this).addClass("selected");
monthIdx = months.indexOf(selected.id);
});
d3.select("#picker").append("li")
.attr("class", "play")
.html("&nbsp;")
.on('click', function(){
playing = !playing;
$(this).attr("class", playing ? "play pause" : "play");
});
setInterval(function(){
if(!playing) return;
monthIdx = (monthIdx+1)%12;
if(selected) $(selected).removeClass("selected");
selected = $("#"+months[monthIdx]).addClass("selected");
}, 90);
selected = $("#Jan").addClass("selected");
}
function loadData(callback) {
var data = {};
var nLoaded = 0;
d3.json("http://dcpos.ch/d3gl/data/pr.json", function(datum){
var domain = [0, 100, 200, 300, 400, 500];
data["pr"] = {};
data["pr"].scale = d3.scale.linear()
.domain(domain)
.range([
"#ffffff", // [-INF, 100)
"#00cc99", // [100, 200)
"#008f6b", // [200, 300)
"#00644b", // [300, 400)
"#004634" // [400, INF]
]);
data["pr"].data = datum;
if(++nLoaded==2) {
callback(data);
}
});
d3.json("http://dcpos.ch/d3gl/data/tas.json", function(datum){
data["tas"] = {};
data["tas"].scale = d3.scale.quantile()
.domain([-40, 40])
.range([
"#000000", // [-40, -30)
"#000099", // [-30, -20)
"#0033cc", // [-20, -10)
"#0066ff", // [-10, 0)
"#0099ff", // [0, 10)
"#00cc66", // [10, 20)
"#ffcc00", // [20, 30)
"#ff6600" // [30, 40]
]);
data["tas"].data = datum;
if(++nLoaded==2) {
callback(data);
}
});
}
function createGlobes(data) {
// create the globe
var globe = d3.gl.globe()
.width(360).height(360)
.texture("http://dcpos.ch/d3gl/img/earth-blank.png")
.transparency(function(body){
return 0.6;
});
var mouseoverPoint;
globe.shapes("countries")
.data(function(climateDataT) {
return data[climateDataT]["data"];
})
.id(function(d){
// the id returned here must match the color in the shape texture
// such that r*10*10 + g*10 + b = id
return country_code_map["alpha_code_to_country"][d["ISO_code"]]["country-code"];
})
.color(function(d){
if(d==mouseoverPoint) return [50, 50, 50, 255];
var values = d["monthly_data"];
if(values.length>0) {
var value = parseInt(d["monthly_data"][monthIdx]["data"]);
var color = data[d["var"]].scale(value);
color = color.slice(1);
var sr = parseInt(color.substring(0, 2), 16);
var sg = parseInt(color.substring(2, 4), 16);
var sb = parseInt(color.substring(4), 16);
return [sr, sg, sb, 255];
}
return [0, 0, 0, 0];
})
.on("mousemove", function(evt) {
if(evt.shape) {
mouseoverPoint = evt.shape;
} else {
mouseoverPoint = null;
}
})
.on("click", function(evt) {
if(evt.shape) {
showDetails(evt, evt.shape);
} else {
$("#bubble").hide();
}
});
d3.select("body").selectAll(".climate-globe")
.data(climateDataTypes).enter()
.append("span").attr("class", "climate-globe")
.call(globe);
}
function showDetails(mouseEvent, data) {
var name = country_code_map["alpha_code_to_country"][data["ISO_code"]]["name"];
var value = months[monthIdx]+": ";
if(data["monthly_data"].length==0){
value += "N/A";
} else {
value += Math.round(data["monthly_data"][monthIdx]["data"]);
value += data["var"]=="pr" ? " mm" : " &deg;C";
}
var size = name.length > 15 ? "10pt" : "12pt";
var height = name.length > 15 ? 60 : 40;
$("#bubble").show()
.css("font-size", size)
.css("height", height + "px")
.css("left", mouseEvent.clientX)
.css("top", mouseEvent.clientY + height/3)
.html(name + "<br />" + value);
}
$(function(){
// create the ui
createControls();
loadData(createGlobes);
});
</script>
<div id="bubble"></div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment