Spinny globe
by Maria Karanasou
HTML
<title>d3.js Spinny Globe from Mike Bostock's SVG Open 2011 keynote</title>
<script src="http://mbostock.github.com/d3/d3.js"></script>
<link type="text/css" rel="stylesheet" href="http://mbostock.github.com/d3/talk/20111018/style.css"/>
<link type="text/css" rel="stylesheet" href="http://mbostock.github.com/d3/talk/20111018/colorbrewer/colorbrewer.css"/>
<body>
<div id="body">
<div id="header">
<div><label for="geochooser">Regions: </label><select id="geochooser">
<option value="1" >Americas</option>
<option value="10" >-North America</option>
<option value="11" >-South America</option>
<option value="2" >EMEA</option>
<option value="20" >-Europe</option>
<option value="21" >-Middle-East</option>
<option value="22" >-Africa</option>
<option value="3" >APAC</option>
<option value="30" >-China</option>
<option value="31" >-India</option>
<option value="32" >-Oceana</option>
</select></div>
<div><label for="proj">Projection: </label><select id="proj">
<option value="equalarea">equalarea</option>
<option value="equidistant">equidistant</option>
<option value="gnomonic">gnomonic</option>
<option value="orthographic" selected>orthographic</option>
<option value="stereographic">stereographic</option>
</select></div>
<div class="tip"></div>
<div><label for="animate">animate:</label>
<input id="animate" type="checkbox" checked>
</div>
</div>
</div>
<svg id="defs">
<defs>
<linearGradient id="gradBlue" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#005C99;stop-opacity:1" />
<stop offset="100%" style="stop-color:#d8efff;stop-opacity:1" />
</linearGradient>
<filter id="glow">
<feColorMatrix...
CSS
svg {
width: 800px;
height: 800px;
pointer-events: all;
}
circle {
fill: #dbe4f0;
}
path {
fill: #aaa;
stroke: #fff;
}
#header {
top: 7px;
left: 685px;
text-align: left;
width: auto;
}
#header div {
font-size: 12px;
}
.tip { color: #999; }
JavaScript
var feature // eventually: all svg paths (countries) of the world
, toggle; // animation on/off control
var projection = d3.geo.azimuthal()
.scale(380)
.origin([-71.03,42.37])
.mode("orthographic")
.translate([400, 400]);
var circle = d3.geo.greatCircle()
.origin(projection.origin());
// TODO fix d3.geo.azimuthal to be consistent with scale
var scale =
{ orthographic: 380
, stereographic: 380
, gnomonic: 380
, equidistant: 380 / Math.PI * 2
, equalarea: 380 / Math.SQRT2
};
var path = d3.geo.path()
.projection(projection);
//Setup zoom behavior
var zoom = d3.behavior.zoom(true)
.translate(projection.origin())
.scale(projection.scale())
.scaleExtent([100, 800])
.on("zoom", move);
var svg = d3.select("#body").append("svg:svg")
.attr("width", 800)
.attr("height", 800)
.on("mousedown", mousedown)
.call(zoom)
.on("dblclick.zoom", null);
//Create the base globe
var backgroundCircle = svg.append("circle")
.attr('cx', 400)
.attr('cy', 400)
.attr('r', 380)
.attr("filter", "url(#glow)")
.attr("fill", "url(#gradBlue)");
if (frameElement) frameElement.style.height = '800px';
d3.json("http://mbostock.github.io/d3/talk/20111018/world-countries.json", function(collection) {
feature = svg.selectAll("path")
.data(collection.features)
.enter().append("svg:path")
.attr("d", clip)
.attr("id", function(d) { return d.properties.name; }) ;
feature.append("svg:title")
.text(function(d) { return d.properties.name; });
var label = svg.selectAll("text")
.data(collection.features)
.enter()
.append("text")
.attr("class", "label")
// update: use position_labels to position the label
//.attr("transform", function(d) { return "translate(" + path.centroid(d) + ")"; })
.text(function(d) { return d.properties.name;} );
// update: use position_labels to...