Skip to content

Commit e9cd6c7

Browse files
authored
Create observablehq-azimuthal.js
1 parent 1a2fbed commit e9cd6c7

File tree

1 file changed

+232
-0
lines changed

1 file changed

+232
-0
lines changed

observablehq-azimuthal.js

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
// URL: https://beta.observablehq.com/@forresto/d3-azimuthal-cities-straight-line-routes
2+
// Title: Azimuthal Artifact
3+
// Author: Forrest Oliphant (@forresto)
4+
// Version: 280
5+
// Runtime version: 1
6+
7+
const m0 = {
8+
id: "e6547e85ad478b83@280",
9+
variables: [
10+
{
11+
inputs: ["md"],
12+
value: (function(md){return(
13+
md`# Azimuthal Artifact
14+
15+
Todo:
16+
- Make a new non-equidistant (logarithmic?) azimuthal projection, to give closer locations more room
17+
- Place names around edge
18+
- Experiment with design to make it suitable for laser engraving
19+
20+
Non-map version, designed as artifact to have spatial intuition of friends, family, memories...
21+
![](https://c2.staticflickr.com/2/1940/43785173620_0b8b5cc6cb_b.jpg)
22+
`
23+
)})
24+
},
25+
{
26+
name: "viewof center",
27+
inputs: ["html","cities","option"],
28+
value: (function(html,cities,option)
29+
{
30+
const form = html`
31+
<form><select name=select>
32+
${cities.map(option)}
33+
<!--
34+
<option value="[0, 0]">Standard aspect</option>
35+
<option value="[0, 90]">North polar aspect</option>
36+
<option value="[0, -90]">South polar aspect</option>
37+
-->
38+
</select></form>`;
39+
form.oninput = () => (form.value = JSON.parse(form.select.value));
40+
form.oninput();
41+
return form;
42+
}
43+
)
44+
},
45+
{
46+
name: "center",
47+
inputs: ["Generators","viewof center"],
48+
value: (G, _) => G.input(_)
49+
},
50+
{
51+
name: "map",
52+
inputs: ["DOM","width","height","d3","projection","graticule","land","sphere","lines"],
53+
value: (function(DOM,width,height,d3,projection,graticule,land,sphere,lines)
54+
{
55+
const context = DOM.context2d(width, height);
56+
const path = d3.geoPath(projection, context);
57+
context.beginPath(),
58+
path(graticule),
59+
(context.strokeStyle = "#eee"),
60+
context.stroke();
61+
context.beginPath(),
62+
path(land),
63+
(context.strokeStyle = "#aaa"),
64+
context.stroke();
65+
context.beginPath(),
66+
path(sphere),
67+
(context.strokeStyle = "#000"),
68+
context.stroke();
69+
context.beginPath(),
70+
path(lines),
71+
(context.strokeStyle = "#000"),
72+
context.stroke();
73+
return context.canvas;
74+
}
75+
)
76+
},
77+
{
78+
name: "viewof zoom",
79+
inputs: ["html"],
80+
value: (function(html){return(
81+
html`<input type=range min=-500 max=500 value=1>`
82+
)})
83+
},
84+
{
85+
name: "zoom",
86+
inputs: ["Generators","viewof zoom"],
87+
value: (G, _) => G.input(_)
88+
},
89+
{
90+
name: "viewof rotateOffset",
91+
inputs: ["html"],
92+
value: (function(html){return(
93+
html`<input type=range min=-360 max=360 value=0></input>`
94+
)})
95+
},
96+
{
97+
name: "rotateOffset",
98+
inputs: ["Generators","viewof rotateOffset"],
99+
value: (G, _) => G.input(_)
100+
},
101+
{
102+
name: "rotate",
103+
inputs: ["center","rotateOffset"],
104+
value: (function(center,rotateOffset)
105+
{
106+
const r = center.map(x => -x);
107+
r[0] += rotateOffset;
108+
return r;
109+
}
110+
)
111+
},
112+
{
113+
name: "projection",
114+
inputs: ["d3","rotate","width","height","zoom","sphere"],
115+
value: (function(d3,rotate,width,height,zoom,sphere){return(
116+
d3
117+
.geoAzimuthalEquidistant()
118+
.rotate(rotate)
119+
.translate([width / 2, height / 2])
120+
.fitExtent([[zoom, zoom], [width - zoom, height - zoom]], sphere)
121+
.precision(0.1)
122+
)})
123+
},
124+
{
125+
name: "height",
126+
inputs: ["width"],
127+
value: (function(width){return(
128+
Math.max(640, width)
129+
)})
130+
},
131+
{
132+
name: "cities",
133+
value: (function(){return(
134+
[
135+
["Tokyo", 35.685, 139.7514],
136+
["New York", 40.6943, -73.9249],
137+
["Mexico City", 19.4424, -99.131],
138+
["Mumbai", 19.017, 72.857],
139+
["Sao Paulo", -23.5587, -46.625],
140+
["Delhi", 28.67, 77.23],
141+
["Shanghai", 31.2165, 121.4365],
142+
["Kolkata", 22.495, 88.3247],
143+
["Dhaka", 23.7231, 90.4086],
144+
["Buenos Aires", -34.6025, -58.3975],
145+
["Los Angeles", 34.114, -118.4068],
146+
["Karachi", 24.87, 66.99],
147+
["Cairo", 30.05, 31.25],
148+
["Rio de Janeiro", -22.925, -43.225],
149+
["Osaka", 34.75, 135.4601],
150+
["Beijing", 39.9289, 116.3883],
151+
["Manila", 14.6042, 120.9822],
152+
["Moscow", 55.7522, 37.6155],
153+
["Istanbul", 41.105, 29.01],
154+
["Paris", 48.8667, 2.3333],
155+
["Seoul", 37.5663, 126.9997],
156+
["Lagos", 6.4433, 3.3915],
157+
["Jakarta", -6.1744, 106.8294],
158+
["Guangzhou", 23.145, 113.325],
159+
["Chicago", 41.8373, -87.6861],
160+
["London", 51.5, -0.1167]
161+
].map(([name, lat, lon]) => [name, lon, lat])
162+
)})
163+
},
164+
{
165+
name: "lines",
166+
inputs: ["cities","center"],
167+
value: (function(cities,center){return(
168+
{
169+
type: "MultiLineString",
170+
coordinates: cities.map(([_, lon, lat]) => [center, [lon, lat]])
171+
}
172+
)})
173+
},
174+
{
175+
name: "option",
176+
inputs: ["html"],
177+
value: (function(html){return(
178+
([name, lon, lat]) =>
179+
html`<option value="[${lon}, ${lat}]">${name}</option>`
180+
)})
181+
},
182+
{
183+
name: "sphere",
184+
value: (function(){return(
185+
{type: "Sphere"}
186+
)})
187+
},
188+
{
189+
name: "graticule",
190+
inputs: ["d3"],
191+
value: (function(d3){return(
192+
d3.geoGraticule10()
193+
)})
194+
},
195+
{
196+
name: "land",
197+
inputs: ["topojson","world"],
198+
value: (function(topojson,world){return(
199+
topojson.feature(world, world.objects.land)
200+
)})
201+
},
202+
{
203+
name: "world",
204+
value: (function(){return(
205+
fetch("https://unpkg.com/world-atlas@1/world/110m.json").then(
206+
response => response.json()
207+
)
208+
)})
209+
},
210+
{
211+
name: "topojson",
212+
inputs: ["require"],
213+
value: (function(require){return(
214+
require("topojson-client@3")
215+
)})
216+
},
217+
{
218+
name: "d3",
219+
inputs: ["require"],
220+
value: (function(require){return(
221+
require("d3-geo@1")
222+
)})
223+
}
224+
]
225+
};
226+
227+
const notebook = {
228+
id: "e6547e85ad478b83@280",
229+
modules: [m0]
230+
};
231+
232+
export default notebook;

0 commit comments

Comments
 (0)