<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<select id="projection-menu"></select>
<div id="container"></div>
<script src="//d3js.org/d3.v4.min.js"></script>
<script src="//d3js.org/d3-geo-projection.v1.min.js"></script>
<script src="//d3js.org/topojson.v2.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
</body>
</html>
//Options, insert projections here
var options = [
{ name: "Mercator", projection: d3.geoMercator() },
{ name: "Hammer", projection: d3.geoHammer() },
{ name: "ConicEqual", projection: d3.geoConicEqualArea() },
{ name: "ConicEqui", projection: d3.geoConicEquidistant() },
{ name: "ConicConformal", projection: d3.geoConicConformal() },
{ name: "Ginzburg8", projection: d3.geoGinzburg8() },
{ name: "Laskowski", projection: d3.geoLaskowski() },
{ name: "Times", projection: d3.geoTimes() },
{ name: "LaGrange", projection: d3.geoLagrange() }
];
options.forEach(function(o) {
o.projection.rotate([0, 0]).center([0, 0]);
});
var interval = setInterval(loop, 1500),
i = 0,
n = options.length - 1;
var c = document.getElementById('container');
var width = c.offsetWidth;
var height = width / 2;
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var graticule = d3.geoGraticule();
var menu = d3.select("#projection-menu")
.on("change", change);
menu.selectAll("option")
.data(options)
.enter().append("option")
.text(function(d) {
return d.name;
});
setup(width, height);
function setup(width, height) {
projection = options[i].projection // N.B. geoPeirceQuincuncial in 1.1+
.translate([(width / 2), (height / 2)])
.scale(width / 2 / Math.PI);
//path = d3.geo.path().projection(projection);
path = d3.geoPath().projection(projection);
svg = d3.select("#container").append("svg")
.attr("width", width)
.attr("height", height)
.append("g");
g = svg.append("g");
g.append("path")
.datum(graticule)
.attr("class", "graticule")
.attr("d", path);
g.append("path")
.datum({
type: "Sphere"
})
.attr("class", "sphere")
.attr("d", path)
.attr("fill", "#f1f1f1")
.attr("stroke", "black")
.attr("opacity", 0.3);
}
d3.queue()
.defer(d3.json, "world-50m.v1.json")
.await(ready);
function ready(error, world) {
if( error ){
console.warn(error);
return;
}
if( world ){
var countries = topojson.feature(world, world.objects.countries).features;
topo = countries;
draw(topo);
}
}
function draw(topo) {
var country = g.selectAll(".country").data(topo);
country.enter().insert("path")
.attr("class", "country")
.attr("d", path)
.style("fill", "black");
}
//Loop / interval / option / update
function loop() {
var j = Math.floor(Math.random() * n);
menu.property("selectedIndex", i = j + (j >= i));
update(options[i]);
}
function change() {
clearInterval(interval);
update(options[this.selectedIndex]);
}
function update(option) {
svg
.selectAll("path")
.transition()
.duration(750)
.attrTween("d", projectionTween(projection, projection = option.projection));
}
function projectionTween(projection0, projection1) {
return function(d) {
var t = 0;
var projection = d3.geoProjection(project)
.scale(1)
.translate([0,0])
.clipAngle(90)
var path = this.path = d3.geoPath()
.projection(projection);
function project(λ, φ) {
λ *= 180 / Math.PI, φ *= 180 / Math.PI;
var p0 = projection0([λ, φ]), p1 = projection1([λ, φ]);
return [(1 - t) * p0[0] + t * p1[0], (1 - t) * -p0[1] + t * -p1[1]];
}
return function(_) {
t = _;
if( _ > 0.2){
projection.clipAngle(null);
}
return path(d);
};
};
}
Output
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |