Inspired by Mike Bostock's satellite projection. Urban areas and coastline data by naturalearthdata
xxxxxxxxxx
<meta charset="utf-8" />
<body>
<div class="map">
</div>
<script src="d3.js"></script>
<script src="d3.geo.projection.min.js"></script>
<script src="topojson.js"></script>
<script src="rbush.js"></script>
<script src="spam.min.js"></script>
<script type='text/javascript'>
var graticule = d3.geo.graticule().step([5, 5]),
width = 900,
height = 650;
var places = {
Rome: [12.39,41.91],
Paris: [2.27, 48.85]
};
d3.json("map.json", function(error, d) {
topojson.presimplify(d)
var map = new StaticCanvasMap({
element: ".map",
width: width,
height: height,
projection: d3.geo.satellite()
.translate([width/2,0])
.distance(1.1)
.scale(2600)
.center([30, 50])
.rotate([0, -42, -40])
.tilt(20)
.clipAngle(Math.acos(1 / 1.1) * 180 / Math.PI - 1e-6),
data: [
{
features: topojson.feature(d, d.objects["land"]),
static: {
// graticule
prepaint: function(parameters, d) {
parameters.context.beginPath();
parameters.path(graticule());
parameters.context.lineWidth = 0.4;
parameters.context.strokeStyle = 'rgb(122,148,149)';
parameters.context.stroke();
},
// coastline
paintfeature: function(parameters, d) {
parameters.context.lineWidth = 0.2;
parameters.context.strokeStyle = "rgba(122, 148, 149, 0.8)";
parameters.context.stroke();
parameters.context.save()
parameters.context.shadowColor = "rgba(122, 148, 149, 0.8)";
parameters.context.shadowBlur = 5
parameters.context.fillStyle = "rgb(255,255,255)";
parameters.context.fill()
parameters.context.restore()
}
}
},{
// countries
features: topojson.feature(d, d.objects["countries"]),
static: {
paintfeature: function(parameters, d) {
parameters.context.lineWidth = 0.2;
parameters.context.strokeStyle = "rgba(80,80,80, 1)";
parameters.context.stroke();
}
}
},
{
features: topojson.feature(d, d.objects["urbanareas"]),
static: {
// painting sphere
prepaint: function(parameters) {
parameters.context.beginPath()
parameters.path({type: "Sphere"})
parameters.context.lineWidth = 1
parameters.context.strokeStyle = "rgb(198, 197, 197)"
parameters.context.stroke()
},
// urban areas
paintfeature: function(parameters, d) {
parameters.context.lineWidth = 0.2;
parameters.context.strokeStyle = "rgba(80,80,80,0.4)";
parameters.context.stroke()
parameters.context.fillStyle = "rgba(161,205,59,0.1)";
parameters.context.fill()
},
// drawing points and line between
postpaint: function(parameters, d) {
var parPoints = parameters.map.settings().projection(places["Paris"]);
var romPoints = parameters.map.settings().projection(places["Rome"]);
parameters.context.moveTo(parPoints[0], parPoints[1])
// create line
parameters.context.save()
parameters.context.setLineDash([5, 5]);
parameters.context.quadraticCurveTo(700, -0, romPoints[0], romPoints[1]);
parameters.context.strokeStyle = "rgba(205,23,25,0.8)";
parameters.context.lineWidth = 2;
parameters.context.stroke();
parameters.context.restore()
d3.entries(places).forEach(function(d,i){
// city names
var points = parameters.map.settings().projection(d.value);
parameters.context.beginPath();
parameters.context.textAlign = "right"
parameters.context.font = "20px sans-serif"
parameters.context.lineWidth = 4;
parameters.context.strokeStyle = 'rgba(255,255,255,0.7)';
parameters.context.strokeText(d.key,points[0] - 10, points[1] + 5)
parameters.context.fillStyle = "rgba(80,80,80, 0.7)";
parameters.context.fillText(d.key, points[0] - 10, points[1] + 5)
parameters.context.stroke()
// points
parameters.context.beginPath();
parameters.context.arc(points[0], points[1] / parameters.scale, 3 , 0, 2 * Math.PI, true);
parameters.context.strokeStyle = "rgba(205,23,25,0.8)";
parameters.context.lineWidth = 4;
parameters.context.stroke();
parameters.context.fillStyle = "rgba(250,250,250,0.8)";
parameters.context.fill();
})
}
}
}
]
})
map.init()
})
</script>
</body>
</html>