Skip to content

Instantly share code, notes, and snippets.

@Fil
Last active Nov 8, 2019
Embed
What would you like to do?
Hwasong-15
license: mit
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