Skip to content

Instantly share code, notes, and snippets.

@Fil
Last active November 8, 2019 07:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Fil/5a55a52da1bb1451d6d07bacc58fec8a to your computer and use it in GitHub Desktop.
Save Fil/5a55a52da1bb1451d6d07bacc58fec8a to your computer and use it in GitHub Desktop.
Hwasong-15
license: mit
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://unpkg.com/d3@4"></script>
<script src="https://unpkg.com/d3-geo-projection"></script>
<script src="https://unpkg.com/versor"></script>
<script src="https://unpkg.com/d3-inertia"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
svg {
cursor: move; /* fallback if grab cursor is unsupported */
cursor: grab;
cursor: -moz-grab;
cursor: -webkit-grab;
}
svg.dragging {
cursor: grabbing;
cursor: -moz-grabbing;
cursor: -webkit-grabbing;
}
</style>
</head>
<body>
<svg>
<style>
.missiles path.hover {
fill: red;
fill-opacity: 0.4;
stroke: black;
stroke-width: 1;
stroke-dasharray: 1;
}
.missiles path {
fill: white;
fill-opacity: 0.01;
stroke: #444;
stroke-dasharray: 5 5;
stroke-width: 0.3;
}
path.pyongyang {
fill: white;
stroke: black
}
text {
font-family: sans-serif;
}
#title {
font-weight: bold;
font-size: 19px;
}
#legend text {
font-family: monospace;
}
#legend {
cursor: pointer;
}
#legend rect {
fill: transparent;
}
#legend .hover rect {
stroke: #eee;
fill: white;
fill-opacity: 0.7;
}
#legend .hover text {
fill: #e00003;
}
#countries {
fill: #d1d1d1;
stroke: #303030;
stroke-width: 0.5;
}
</style>
<g id="map"></g>
<text id="title" transform="translate(0,20)">Portée supposée des missiles coréens</text>
</svg>
<script>
var svg = d3.select("svg");
var map = svg.select('#map');
map.append('path')
.datum({type:"Sphere"})
.attr('fill', '#eee')
.attr('stroke', '#111');
map.append('path')
.datum(d3.geoGraticule())
.attr('fill', 'none')
.attr('stroke', '#999');
var countries = map.append('path')
.attr('id', 'countries');
d3.json('countries.geojson', function(err, json) {
countries.datum(d3.geoStitch(json));
render();
})
var pyongyang = [125.75432, 39.03385]
var ranges = d3.csvParse(`date,name,range
2017-11,Hwasong-15,13000
2017-07,Hwasong-14,10400
2017-05,Hwasong-12,4500
2016-04,Musudan,3500
1990-05,Nodong,1300`);
ranges.forEach(d => d.l = +d.range / 6371 * 180 / Math.PI);
ranges = ranges.sort((a,b) => d3.descending(a.date, b.date))
var hover = 0;
var legends = svg.append('g')
.attr('id', 'legend')
.selectAll('g')
.data(ranges.map(d => (d.properties = d, d)))
.enter()
.append('g')
.attr('transform', (d,i) => `translate(${[0, i*20 + 60]})`)
.on('mouseover click', d => {
hover = d.properties.date;
missiles.classed('hover', d => d.properties.date == hover);
legends.classed('hover', d => d.properties.date == hover);
});
legends.append('rect')
.attr('width', 250)
.attr('height', 20)
.attr('y', -15)
var f = d3.formatLocale({thousands: " ", grouping:[3]}).format(" >6,.2r");
legends.append('text')
.text(d => `${d.date}  ${f(d.range)} km - ${d.name}`)
ranges = ranges.sort((a,b) => b.l - a.l)
var missiles = map.append('g')
.classed('missiles', true)
.selectAll('path')
.data(ranges.map(d => {
var c = d3.geoCircle()
.center(pyongyang)
.radius(d.l)
();
c.properties = d;
return c;
}))
.enter()
.append('path')
.attr("id", (d, i) => "d" + i)
.on("mouseover click", d => {
return;
hover = d.properties.date;
missiles.classed('hover', d => d.properties.date == hover);
legends.classed('hover', d => d.properties.date == hover);
});
map.append('path')
.classed('pyongyang', true)
.datum({type: "Point", coordinates: pyongyang});
var projection = d3.geoOrthographic();
if(projection.rotate) projection.rotate([-140,-32,-32]);
projection.translate([550,250]);
var path = d3.geoPath(projection);
// svg
render = function() {
var width = Math.min(960, window.innerWidth),
height = Math.min(600, window.innerHeight),
margin = 25;
if (width < 400) // en petit écran, essayer de passer sous les liens
{
height += 100;
margin = 10;
}
projection.fitExtent([[(width - height)/2 - 2 * margin, margin * 2], [width - margin, height - margin]], {
type: "Sphere"
});
svg.attr("width", width).attr("height", height);
map.selectAll('path').attr('d', path);
}
d3.geoInertiaDrag(svg, render, projection);
d3.interval(render, 500); // for window.resize
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment