forked from mbostock's block: Satellite Projection
forked from basilesimon's block: Satellite Projection
| license: gpl-3.0 |
forked from mbostock's block: Satellite Projection
forked from basilesimon's block: Satellite Projection
| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <style> | |
| </style> | |
| <body> | |
| <script src="//d3js.org/d3.v4.min.js"></script> | |
| <script src="//d3js.org/d3-geo-projection.v2.min.js"></script> | |
| <script src="//d3js.org/topojson.v2.js"></script> | |
| <script src="//unpkg.com/[email protected]/build/d3-jetpack.js"></script> | |
| <button onclick="zoom()">click to zoom</button> | |
| <canvas width="960" height="500"></canvas> | |
| <script> | |
| const canvas = d3.select("canvas"); | |
| const width = canvas.property("width"); | |
| const height = canvas.property("height"); | |
| let context = canvas.node().getContext("2d"); | |
| let projection = d3.geoSatellite() | |
| .distance(1.1) | |
| .scale(5000) | |
| .rotate([-38, -33, -30]) | |
| .center([0, 2]) | |
| .tilt(30) | |
| .precision(0.1); | |
| let path = d3.geoPath(projection, context); | |
| const zoom = d3.zoom() | |
| //.scaleExtent([5000, 20000]) | |
| .scaleExtent([1, 10]) | |
| .on('zoom', zoomed); | |
| const graticule = d3.geoGraticule() | |
| .extent([[-10,30], [80, 80]]) | |
| .step([3, 3]); | |
| let render = function() {}; | |
| const draw = (error, land, circle, camp) => { | |
| render = (projection, context) => { | |
| context.clearRect(0, 0, width, height); | |
| path = d3.geoPath(projection, context); | |
| context.strokeStyle = "#ccc"; | |
| context.fillStyle = "#fff"; | |
| context.beginPath(); | |
| path(topojson.feature(land, land.objects.ne_10m_admin_0_countries2)); | |
| context.fill(); | |
| context.stroke(); | |
| context.closePath(); | |
| context.beginPath(); | |
| context.strokeStyle = "rgba(255,0,0,0.3)"; | |
| context.fillStyle = "rgba(255,0,0,0.1)"; | |
| path(topojson.feature(circle, circle.objects.Circle_Measure)); | |
| context.stroke(); | |
| context.fill(); | |
| context.closePath(); | |
| const shelters = topojson.feature(camp, camp.objects.Rukban_Structures_20190121).features; | |
| for (let i=0; i<shelters.length; i++) { | |
| context.beginPath(); | |
| const tent = shelters[i]; | |
| context.moveTo(projection(tent.geometry.coordinates)[0] + 1, projection(tent.geometry.coordinates)[1]); | |
| context.arc(projection(tent.geometry.coordinates)[0], projection(tent.geometry.coordinates)[1], 1, 0, 2 * Math.PI); | |
| context.fillStyle = "rgba(0,0,0,0.1)"; | |
| context.fill(); | |
| context.closePath(); | |
| } | |
| }; | |
| canvas.call(zoom); | |
| render(projection, context); | |
| } | |
| function zoomed () { | |
| const t = d3.event.transform; | |
| console.log(t, d3.zoomIdentity); | |
| context.save(); | |
| // const proj = projection | |
| // //.translate([t.x, t.y]) | |
| // .scale(t.k); | |
| context.scale(t.k, t.k); | |
| context.translate(t.x, t.y); | |
| render(projection, context); | |
| context.restore(); | |
| } | |
| d3.queue() | |
| .defer(d3.json, "https://gist.githubusercontent.com/basilesimon/e15cc6647a5ecc3c2c9b961215e8bf6b/raw/5733bff346be28f61ca2e2dcb982a82a48733bcd/sat.json") | |
| .defer(d3.json, "https://gist.githubusercontent.com/basilesimon/20178b9d63dbda0fb8ed14590fcca036/raw/3214d4c452f83f7538d0b2c20e30d535711e8a80/circle.json") | |
| .defer(d3.json, "https://gist.githubusercontent.com/basilesimon/614713d27f4c55d0392d77501f12b420/raw/8443dc30bb5f9b129a8e67e658c8c901a154f8fc/rukban.json") | |
| .await(draw); | |
| </script> |