This small example was made to explore how to add geo satellite positions onto a world map.
forked from d3noob's block: Adding names to places
xxxxxxxxxx
<meta charset="utf-8">
<style>
path {
stroke: white;
stroke-width: 0.25px;
fill: grey;
}
svg {
/*background: #e6f2ff;*/
background: #7BB5FF;
fill-opacity: 1;
}
.graticule {
fill: none;
stroke: #666;
stroke-width: 0.2px;
stroke-opacity: 1;
}
.city {
fill:yellow;
stroke:black;
stroke-opacity: 1;
fill-opacity: 1;
}
.cityname {
fill-opacity: 1;
fill: black;
font-size:10px;
font-family: "Arial", sans-serif;
}
.country {
stroke: #fff;
fill: #336633;
fill-opacity: 0.7;
stroke-width: 0.5px;
}
.equator {
stroke: black;
stroke-width: 1px;
}
div.tooltip {
color: #222;
background: #fff;
border-radius: 3px;
box-shadow: 0px 0px 2px 0px #a6a6a6;
padding: .2em;
text-shadow: #f5f5f5 0 1px 0;
opacity: 0.9;
position: absolute;
font-size:12px;
font-family: "Arial", sans-serif;
}
.beam {
fill: red;
fill-opacity: 0.15;
stroke: #B10000;
stroke-linejoin: round;
stroke-width: 1;
pointer-events: none; /* ensures that mouseover countries works thru the beam */
}
</style>
<body>
<div id="map"></div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-array.v1.min.js"></script>
<script src="https://d3js.org/d3-geo.v1.min.js"></script>
<script src="https://d3js.org/d3-geo-projection.v2.min.js"></script>
<script src="https://d3js.org/topojson.v1.min.js"></script>
<script src="https://d3js.org/queue.v1.min.js"></script>
<script>
var width = 960,
height = 800;
//var projection = d3.geoOrthographic()
var projection = d3.geoMercator()
.center([0, 50 ])
.scale(150)
.rotate([0,0]);
var graticule = d3.geoGraticule10();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
// setup the filter for the country labels
var defs = svg.append("defs")
var filter = defs.append("filter")
.attr("x","0")
.attr("y","0")
.attr("width","1")
.attr("height","1")
.attr("id","solid")
filter.append("feFlood")
.attr("flood-color","#ffff99")
filter.append("feComposite")
.attr("in","SourceGraphic")
// end filter for country labels
var path = d3.geoPath()
.projection(projection);
var g = svg.append("g");
// Some code for the country label tooltip
var offsetL = document.getElementById('map').offsetLeft+10;
var offsetT = document.getElementById('map').offsetTop+10;
var tooltip = d3.select("#map")
.append("div")
.attr("class", "tooltip hidden");
// TODO: use d3-queue ??
// load data for drawing the world, countries and earth stations
queue()
.defer(d3.json,"world-110m2.json") // world map topojson
.defer(d3.tsv, "countries.tsv") // country name data
.defer(d3.csv, "cities.csv") // the earth station locations
.await(ready);
// draw the world, countries and stations
function ready(error, world, names, cities) {
if (error) throw error;
var countries = topojson.feature(world, world.objects.countries).features,
neighbors = topojson.neighbors(world.objects.countries.geometries);
// draw the earth stations - these are appended as topojson points
// therefore they rotate with the earth
g.selectAll(".station")
.data(cities)
.enter()
.append("path")
.datum(function(d){
return {type: "Point", coordinates:[d.lon,d.lat] }
})
.attr("class", "city")
.attr("d", path)
.on("mousemove", function(d) {
console.log(d)
label = "Lat: " + d.coordinates[0] + "<br/>Lon: " + + d.coordinates[1];
var mouse = d3.mouse(svg.node())
.map( function(d) { return parseInt(d); } );
tooltip.classed("hidden", false)
.attr("style", "left:"+(mouse[0]+offsetL)+"px;top:"+(mouse[1]+offsetT)+"px")
.html(label);
})
// the station labels, these are positioned by a functions, which means
// we can refresh them as the globe is rotated
g.selectAll("text")
.data(cities)
.enter()
.append("text")
.attr("class", "cityname")
.attr("x", function(d) {
return projection([d.lon, d.lat])[0];
})
.attr("y", function(d) {
return projection([d.lon, d.lat])[1];
})
.attr("dx", 5) // set y position of bottom of text
.attr("dy", 5) // set y position of bottom of text
.attr("text-anchor", "start") // set anchor y justification
.attr("filter", 'url(#solid)')
.text(function(d) { return d.city })
// folds the TSV country name data (separate file) into the
// countries object
countries = countries.filter(function(d) {
return names.some(function(n) {
if (d.id == n.id) return d.name = n.name;
});
}).sort(function(a, b) {
return a.name.localeCompare(b.name);
});
// show countries and colour them on a scale
g.selectAll(".country")
.data(countries)
.enter().insert("path", ".graticule")
.attr("class", "country")
.attr("d", path)
.on('mouseenter', function(d, i) {
d3.select(this).style('fill','#339933');
})
.on('mouseleave', function(d, i) {
d3.select(this).style('fill','#336633');
tooltip.classed("hidden", true);
})
.on("mousemove", function(d) {
label = d.name;
var mouse = d3.mouse(svg.node())
.map( function(d) { return parseInt(d); } );
tooltip.classed("hidden", false)
.attr("style", "left:"+(mouse[0]+offsetL)+"px;top:"+(mouse[1]+offsetT)+"px")
.html(label);
})
};
g.append("path")
.datum(graticule)
.attr("class", "graticule")
.attr("d", path);
g.append("path")
.datum({type: "LineString", coordinates: [[-180, 0], [-90, 0], [0, 0], [90, 0], [180, 0]]})
.attr("class", "equator")
.attr("d", path);
// Draw the beams isobands
// TODO: load from a file
g.append("path")
.datum({type: "Polygon", coordinates:
[[[0, 55],[40,45],[50,0],[0, -33],[-37, 17],[0, 55]]]})
.attr("class", "beam")
.attr("d", path);
g.append("path")
.datum({type: "Polygon", coordinates:
[[[0, 45],[40,25],[40,0],[0, -3],[-27, 20],[0, 55]]]})
.attr("class", "beam")
.attr("d", path);
g.append("path")
.datum({type: "Polygon", coordinates:
[[[0, 35],[30,25],[20,10],[0, 10],[-7, 20],[0, 55]]]})
.attr("class", "beam")
.attr("d", path);
// zoom and pan
var zoom = d3.zoom()
.scaleExtent([1, 20])
.translateExtent([[0,0],[960,600]])
.extent([[0,0],[960,460]])
.on("zoom",function() {
g.attr("transform",d3.event.transform)
g.selectAll("circle")
.attr("d", path.projection(projection));
});
svg.call(zoom)
</script>
</body>
</html>
Modified http://d3js.org/topojson.v1.min.js to a secure url
https://d3js.org/d3.v4.min.js
https://d3js.org/d3-array.v1.min.js
https://d3js.org/d3-geo.v1.min.js
https://d3js.org/d3-geo-projection.v2.min.js
https://d3js.org/topojson.v1.min.js
https://d3js.org/queue.v1.min.js