Skip to content

Instantly share code, notes, and snippets.

@VisDockHub
Last active October 26, 2015 18:54
Show Gist options
  • Select an option

  • Save VisDockHub/9082845 to your computer and use it in GitHub Desktop.

Select an option

Save VisDockHub/9082845 to your computer and use it in GitHub Desktop.
Faux 3D Shaded Globe

This Faux 3D Shaded Globe example has a faux 3D spherical globe projected onto 2D space and it allows users to rotate the globe about the origin. The globe has individual countries with labels for cities of significant size. This is a rather interesting example in that the visualization contains path elements and text elements both of which get updated if users rotate the globe. The VisDock toolkit has been integrated into this Faux 3D Shaded Globe example built with D3.js (found here) by Derek Watkins. For more information about VisDock, please cick on the link.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
.land {
fill: rgb(117, 87, 57);
stroke-opacity: 1;
}
.countries path {
stroke: rgb(80, 64, 39);
stroke-linejoin: round;
stroke-width:.5;
fill: rgb(117, 87, 57);
opacity: .1;
}
.countries path:hover {
fill-opacity:.1;
stroke-width:1;
opacity: 1;
}
.graticule {
fill: none;
stroke: black;
stroke-width:.5;
opacity:.2;
}
.labels {
font: 8px sans-serif;
fill: black;
opacity: .5;
}
.noclicks {
pointer-events:none;
}
.point{
opacity:.6;
}
</style>
<body>
<link href="http://rawgithub.com/VisDockHub/NewVisDock/master/master/visdock.css" rel="stylesheet" type="text/css"/>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/queue.v1.min.js"></script>
<script src="http://d3js.org/topojson.v0.min.js"></script>
<script src="http://rawgithub.com/VisDockHub/NewVisDock/master/master/visdock.js"></script>
<script src="http://rawgithub.com/VisDockHub/NewVisDock/master/master/2D.js"></script>
<script src="http://rawgithub.com/VisDockHub/NewVisDock/master/master/IntersectionUtilities.js"></script>
<script src="http://rawgithub.com/VisDockHub/NewVisDock/master/master/visdock.utils.js"></script>
<script>
// Lots of code from:
// http://bl.ocks.org/3757125
// http://bl.ocks.org/3795040
d3.select(window)
.on("mousemove", mousemove)
.on("mouseup", mouseup);
var width = 960,
height = 500;
VisDock.init("body", {width: 960, height: 700});
AnnotatedByData.layerTypes = [".country"]
var viewport = VisDock.getViewport();
var proj = d3.geo.orthographic()
.scale(220)
.translate([width / 2, height / 2])
.clipAngle(90);
var path = d3.geo.path().projection(proj).pointRadius(1.5);
var graticule = d3.geo.graticule();
var svg = viewport;
d3.selectAll('svg')
.on("mousedown", mousedown);
queue()
.defer(d3.json, "/VisDockHub/raw/9082845/world-110m.json")
.defer(d3.json, "places.json")
.await(ready);
function ready(error, world, places) {
VisDock.startChrome();
var ocean_fill = svg.append("defs").append("radialGradient")
.attr("id", "ocean_fill")
.attr("cx", "75%")
.attr("cy", "25%");
ocean_fill.append("stop").attr("offset", "5%").attr("stop-color", "#ddf");
ocean_fill.append("stop").attr("offset", "100%").attr("stop-color", "#9ab");
var globe_highlight = svg.append("defs").append("radialGradient")
.attr("id", "globe_highlight")
.attr("cx", "75%")
.attr("cy", "25%");
globe_highlight.append("stop")
.attr("offset", "5%").attr("stop-color", "#ffd")
.attr("stop-opacity","0.6");
globe_highlight.append("stop")
.attr("offset", "100%").attr("stop-color", "#ba9")
.attr("stop-opacity","0.2");
var globe_shading = svg.append("defs").append("radialGradient")
.attr("id", "globe_shading")
.attr("cx", "50%")
.attr("cy", "40%");
globe_shading.append("stop")
.attr("offset","50%").attr("stop-color", "#9ab")
.attr("stop-opacity","0")
globe_shading.append("stop")
.attr("offset","100%").attr("stop-color", "#3e6184")
.attr("stop-opacity","0.3")
var drop_shadow = svg.append("defs").append("radialGradient")
.attr("id", "drop_shadow")
.attr("cx", "50%")
.attr("cy", "50%");
drop_shadow.append("stop")
.attr("offset","20%").attr("stop-color", "#000")
.attr("stop-opacity",".5")
drop_shadow.append("stop")
.attr("offset","100%").attr("stop-color", "#000")
.attr("stop-opacity","0")
svg.append("ellipse")
.attr("cx", 440).attr("cy", 450)
.attr("rx", proj.scale()*.90)
.attr("ry", proj.scale()*.25)
.attr("class", "noclicks")
.style("fill", "url(#drop_shadow)");
svg.append("circle")
.attr("cx", width / 2).attr("cy", height / 2)
.attr("r", proj.scale())
.attr("class", "noclicks")
.style("fill", "url(#ocean_fill)");
svg.append("path")
.datum(topojson.object(world, world.objects.land))
.attr("class", "land")
.attr("d", path);
svg.append("path")
.datum(graticule)
.attr("class", "graticule noclicks")
.attr("d", path);
svg.append("circle")
.attr("cx", width / 2).attr("cy", height / 2)
.attr("r", proj.scale())
.attr("class","noclicks")
.style("fill", "url(#globe_highlight)");
svg.append("circle")
.attr("cx", width / 2).attr("cy", height / 2)
.attr("r", proj.scale())
.attr("class","noclicks")
.style("fill", "url(#globe_shading)");
svg.append("g").attr("class","points")
.selectAll("text").data(places.features)
.enter().append("path")
.attr("class", "point")
.attr("d", path);
svg.append("g").attr("class","labels")
.selectAll("text").data(places.features)
.enter().append("text")
.attr("class", "label")
.text(function(d) { return d.properties.name })
var id = 0
var country = svg.selectAll(".countries")
.data(topojson.object(world, world.objects.countries).geometries)
.enter().append("g")
.attr("class", "countries")
country.append("path")
.attr("class", "country")
.attr("d", path);
position_labels();
VisDock.finishChrome();
}
function position_labels() {
VisDock.startChrome();
var centerPos = proj.invert([width/2,height/2]);
var arc = d3.geo.greatArc();
svg.selectAll(".label")
.attr("text-anchor",function(d) {
var x = proj(d.geometry.coordinates)[0];
return x < width/2-20 ? "end" :
x < width/2+20 ? "middle" :
"start"
})
.attr("transform", function(d) {
var loc = proj(d.geometry.coordinates),
x = loc[0],
y = loc[1];
var offset = x < width/2 ? -5 : 5;
return "translate(" + (x+offset) + "," + (y-2) + ")"
})
.style("display",function(d) {
var d = arc.distance({source: d.geometry.coordinates, target: centerPos});
return (d > 1.57) ? 'none' : 'inline';
})
VisDock.finishChrome();
}
// modified from http://bl.ocks.org/1392560
var m0, o0;
function mousedown() {
if (viewport.attr("pointer-events") != "none"){
VisDock.startChrome();
m0 = [d3.event.pageX, d3.event.pageY];
o0 = proj.rotate();
d3.event.preventDefault();
VisDock.finishChrome();
}
}
function mousemove() {
if (m0) {
var m1 = [d3.event.pageX, d3.event.pageY]
, o1 = [o0[0] + (m1[0] - m0[0]) / 6, o0[1] + (m0[1] - m1[1]) / 6];
o1[1] = o1[1] > 30 ? 30 :
o1[1] < -30 ? -30 :
o1[1];
proj.rotate(o1);
refresh();
}
}
function mouseup() {
if (m0) {
mousemove();
m0 = null;
}
}
function refresh() {
VisDock.startChrome();
svg.selectAll(".land").attr("d", path);
svg.selectAll(".countries path").attr("d", path);
svg.selectAll(".graticule").attr("d", path);
svg.selectAll(".point").attr("d", path);
position_labels();
AnnotatedByData.update();
VisDock.finishChrome();
}
VisDock.eventHandler = {
getHitsPolygon : function(points, inclusive) {
var shapebound = new createPolygon(points);
return shapebound.intersectPath(d3.selectAll(".country")[0], inclusive)
},
getHitsLine : function(points, inclusive) {
var shapebound = new createLine(points);
return shapebound.intersectPath(d3.selectAll(".country")[0], inclusive)
},
getHitsEllipse : function(points, inclusive) {
var shapebound = new createEllipse(points);
return shapebound.intersectPath(d3.selectAll(".country")[0], inclusive)
},
setColor : function(hits) {
QueryManager.layers[num - 1] = [];
for (var i = 0; i < hits.length; i++) {
var str = hits[i].getAttributeNS(null, "transform");
var d = hits[i].getAttributeNS(null, "d")
QueryManager.layers[num - 1][i] = d3.select(hits[i].parentNode).append("path").attr("transform", str)
.attr("d", d)
.attr("style", "fill: "+VisDock.color[num - 1] +"; stroke: " + VisDock.color[num - 1] + "; opacity: 0.5; pointer-events: none")
.attr("class", "VisDockPathLayer")
}
},
changeColor : function(color, query, index) {
var vis = VisDock.utils.getQueryVisibility(index);
for (var i = 0; i < query.length; i++) {
query[i][0][0].setAttributeNS(null, "style", "stroke: " + color + "; fill:none; opacity: " + vis)
}
},
changeVisibility : function(vis, query, index) {
var color = VisDock.utils.getQueryColor(index);
for (var i = 0; i < query.length; i++) {
query[i][0][0].setAttributeNS(null, "style", "fill: " + color + "; opacity: " + vis)
}
},
removeColor : function(hits, index) {
for (var i = 0; i < hits.length; i++) {
hits[i].remove();
}
},
QueryClick : function(query, index) {
}
}
//Panel.x = 75;
//Panel.y = 100;
//Panel.setTransform();
BirdView.init(viewport, 960, 700)
d3.select(self.frameElement).style("width", "960px")
d3.select(self.frameElement).style("height", "700px")
</script>
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.
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment