Skip to content

Instantly share code, notes, and snippets.

@KoGor
Last active November 7, 2023 19:30
Show Gist options
  • Save KoGor/5994804 to your computer and use it in GitHub Desktop.
Save KoGor/5994804 to your computer and use it in GitHub Desktop.
Earth globe

Интерактивный глобус с возможностью вращения мышкой и центрированием на выбранную страну. Подробнее о создании можно почитать на Хабрахабре.

This projected is licensed under the terms of the MIT license.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Earth globe</title>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script src="http://d3js.org/queue.v1.min.js"></script>
</head>
<style type="text/css">
.water {
fill: #00248F;
}
.land {
fill: #A98B6F;
stroke: #FFF;
stroke-width: 0.7px;
}
.land:hover {
fill:#33CC33;
stroke-width: 1px;
}
.focused {
fill: #33CC33;
}
select {
position: absolute;
top: 20px;
left: 580px;
border: solid #ccc 1px;
padding: 3px;
box-shadow: inset 1px 1px 2px #ddd8dc;
}
.countryTooltip {
position: absolute;
display: none;
pointer-events: none;
background: #fff;
padding: 5px;
text-align: left;
border: solid #ccc 1px;
color: #666;
font-size: 14px;
font-family: sans-serif;
}
</style>
<body>
<script>
var width = 600,
height = 500,
sens = 0.25,
focused;
//Setting projection
var projection = d3.geo.orthographic()
.scale(245)
.rotate([0, 0])
.translate([width / 2, height / 2])
.clipAngle(90);
var path = d3.geo.path()
.projection(projection);
//SVG container
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
//Adding water
svg.append("path")
.datum({type: "Sphere"})
.attr("class", "water")
.attr("d", path);
var countryTooltip = d3.select("body").append("div").attr("class", "countryTooltip"),
countryList = d3.select("body").append("select").attr("name", "countries");
queue()
.defer(d3.json, "/d/5685937/world-110m.json")
.defer(d3.tsv, "/d/5685937/world-110m-country-names.tsv")
.await(ready);
//Main function
function ready(error, world, countryData) {
var countryById = {},
countries = topojson.feature(world, world.objects.countries).features;
//Adding countries to select
countryData.forEach(function(d) {
countryById[d.id] = d.name;
option = countryList.append("option");
option.text(d.name);
option.property("value", d.id);
});
//Drawing countries on the globe
var world = svg.selectAll("path.land")
.data(countries)
.enter().append("path")
.attr("class", "land")
.attr("d", path)
//Drag event
.call(d3.behavior.drag()
.origin(function() { var r = projection.rotate(); return {x: r[0] / sens, y: -r[1] / sens}; })
.on("drag", function() {
var rotate = projection.rotate();
projection.rotate([d3.event.x * sens, -d3.event.y * sens, rotate[2]]);
svg.selectAll("path.land").attr("d", path);
svg.selectAll(".focused").classed("focused", focused = false);
}))
//Mouse events
.on("mouseover", function(d) {
countryTooltip.text(countryById[d.id])
.style("left", (d3.event.pageX + 7) + "px")
.style("top", (d3.event.pageY - 15) + "px")
.style("display", "block")
.style("opacity", 1);
})
.on("mouseout", function(d) {
countryTooltip.style("opacity", 0)
.style("display", "none");
})
.on("mousemove", function(d) {
countryTooltip.style("left", (d3.event.pageX + 7) + "px")
.style("top", (d3.event.pageY - 15) + "px");
});
//Country focus on option select
d3.select("select").on("change", function() {
var rotate = projection.rotate(),
focusedCountry = country(countries, this),
p = d3.geo.centroid(focusedCountry);
svg.selectAll(".focused").classed("focused", focused = false);
//Globe rotating
(function transition() {
d3.transition()
.duration(2500)
.tween("rotate", function() {
var r = d3.interpolate(projection.rotate(), [-p[0], -p[1]]);
return function(t) {
projection.rotate(r(t));
svg.selectAll("path").attr("d", path)
.classed("focused", function(d, i) { return d.id == focusedCountry.id ? focused = d : false; });
};
})
})();
});
function country(cnt, sel) {
for(var i = 0, l = cnt.length; i < l; i++) {
if(cnt[i].id == sel.value) {return cnt[i];}
}
};
};
</script>
</body>
</html>
@JasonThomasData
Copy link

These are your datasets with updated names. You had Kosovo and Somaliland missing. I've arbitrarily given them the codes 412 and 708 respectively.

@JasonThomasData
Copy link

One other thing, there's another instance of "id":-99 in the geo file, and that's Cyprus. The map divides Cyprus into the Turkish-conrolled north and Republic south, but they are one country - http://europa.eu/about-eu/countries/member-countries/cyprus/index_en.htm

@Fallenstedt
Copy link

Fallenstedt commented May 8, 2017

Edit
You can locate raw json files at the bottom here: https://gist.github.com/mbostock/4090846

Hey Jason, the countries JSON file is incomplete. Ive found some similar JSON files online, but I was curious if you could share a link to the full file? What makes your json file unique is that the countries are organized by "id" rather than an ISO code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment