xxxxxxxxxx
<meta charset="utf-8">
<style>
.graticule {
fill: none;
stroke: #444;
stroke-width: 0.6;
stroke-opacity: 0.4;
}
.edge {
fill: none;
stroke: #444;
stroke-width: 0.8;
stroke-opacity: 0.5;
}
.land {
fill: #444;
fill-opacity: 0.6;
stroke: #444;
stroke-opacity: 0.7;
stroke-width: 1.5;
}
.countries path {
fill: #ddd;
fill-opacity: 0.4;
stroke: #444;
stroke-linejoin: round;
stroke-width: 0.4;
stroke-opacity: 0.2;
}
.countries path:hover {
fill-opacity: 0.6;
stroke-width: 1.1;
stroke-opacity: 0.5;
}
.labels {
font: 12px sans-serif;
fill: #444;
}
.point{
fill: #eee;
stroke: #444;
stroke-width: 1;
stroke-opacity: 1;
}
.noclick {
pointer-events:none;
}
</style>
<body>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="https://d3js.org/queue.v1.min.js"></script>
<script src="https://d3js.org/topojson.v0.min.js"></script>
<script>
var width = 958,
height = 498;
var projection = d3.geo.orthographic()
.scale(245)
.translate([width/2, height/2])
.precision(0.1)
.rotate([52.8, -49.6])
.clipAngle(90)
.clipExtent([[1, 1], [width - 1, height - 1]])
// scales for fading/sizing labels/points
var opacityScale = d3.scale.linear()
.domain([200, 150])
.range([1,0]);
var ptSizeScale = d3.scale.linear()
.domain([500, 150])
.range([12,7]);
var path = d3.geo.path().projection(projection).pointRadius(2);
var graticule = d3.geo.graticule();
d3.select(window)
.on("mousemove", mouseMove)
.on("mouseup", mouseUp);
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height)
.on("mousedown", mouseDown)
.call(d3.behavior.zoom()
.translate(projection.translate())
.scale(projection.scale())
.scaleExtent([50,500])
.on("zoom", function() {
reZoom();
})
);
// queue for loading topojson and places data
queue()
.defer(d3.json, "world-110m.json")
.defer(d3.json, "world-places.json")
.await(ready);
function ready(error, world, places) {
// graticule
svg.append("path")
.datum(graticule)
.attr("class", "graticule noclick")
.attr("d", path);
// land shape
svg.append("path")
.datum(topojson.object(world, world.objects.land))
.attr("class", "land noclick")
.attr("d", path);
// country shapes
svg.append("g").attr("class", "countries")
.selectAll("path")
.data(topojson.object(world, world.objects.countries).geometries)
.enter().append("path")
.attr("class", "countries")
.attr("d", path)
.on("mouseover", function(d) {
console.log("country id: " + d.id);
});
// edge sphere
svg.append("path")
.datum({type: "Sphere"})
.attr("class", "edge noclick")
.attr("d", path);
// place points
svg.append("g").attr("class","points noclick")
.selectAll("text")
.data(places.features)
.enter().append("path")
.attr("class", "point")
.attr("d", path);
// place labels
svg.append("g").attr("class","labels noclick")
.selectAll("text")
.data(places.features)
.enter().append("text")
.attr("class", "label")
.text(function(d) {
return d.properties.name;
});
reDraw();
}
function positionLabels() {
var centerPos = projection.invert([width/2,height/2]);
var arc = d3.geo.greatArc();
var s = projection.scale();
// labels
svg.selectAll(".label")
.attr("text-anchor",function(d) {
var x = projection(d.geometry.coordinates)[0];
if (x < (width/2) - 20) {
return "end";
} else if (x < (width/2) + 20) {
return "middle";
} else {
return "start";
}
})
.attr("transform", function(d) {
var loc = projection(d.geometry.coordinates),
x = loc[0],
y = loc[1],
xoffset = 6,
yoffset = -3;
if (x < (width/2)) {
xoffset = -6;
}
if (x < (width/2) - 20) {
yoffset = -1;
} else if (x < (width/2) + 20) {
yoffset = -6;
} else {
yoffset = -1;
}
return "translate(" + (x + xoffset) + "," + (y + yoffset) + ")";
})
.style("opacity", function() {
return opacityScale(s);
})
.style("font-size", function() {
return ptSizeScale(s);
})
.style("display",function(d) {
var dist = arc.distance({source: d.geometry.coordinates, target: centerPos});
if (dist > 1.57) {
return 'none';
} else {
return 'inline';
}
});
// points
svg.selectAll(".point")
.style("opacity", function() {
return opacityScale(s);
});
}
function reDraw() {
svg.selectAll("path").attr("d", path);
positionLabels();
}
function reZoom() {
if (d3.event) { projection.scale(d3.event.scale); }
svg.selectAll("*").attr("d", path);
positionLabels();
}
// window mousemove
function mouseMove() {
if (m0) {
// limit vertical rotation between 55 & -55
var m1 = [d3.event.pageX, d3.event.pageY],
o1 = [o0[0] + (m1[0] - m0[0]) / 6, o0[1] + (m0[1] - m1[1]) / 6];
if (o1[1] > 55) {
o1[1] = 55;
}
if (o1[1] < -55) {
o1[1] = -55;
}
projection.rotate(o1);
reDraw();
}
}
// window mouseup
function mouseUp() {
if (m0) {
mouseMove();
m0 = null;
}
}
// svg mousedown
var m0, o0;
function mouseDown() {
m0 = [d3.event.pageX, d3.event.pageY];
o0 = projection.rotate();
d3.event.preventDefault();
}
</script>
</body>
Modified http://d3js.org/d3.v3.min.js to a secure url
Modified http://d3js.org/queue.v1.min.js to a secure url
Modified http://d3js.org/topojson.v0.min.js to a secure url
https://d3js.org/d3.v3.min.js
https://d3js.org/queue.v1.min.js
https://d3js.org/topojson.v0.min.js