-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
584 lines (449 loc) · 16.5 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
<!DOCTYPE html><html><head><title></title><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" /><style type='text/css'>
body {
font-family: 'Helvetica';
letter-spacing:-5px;
background:#000;
background-size:100%;
color:#fff;
margin:0;
padding:0;
font-weight:bold;
}
h1, h2, h3, p {
margin:0;
}
em, a {
font-style:normal;
color:#8dbd0c;
}
a {
background: #34d0e7;
color:#000;
text-decoration:none;
}
img {
width:100%;
}
div {
cursor:pointer;
cursor:hand;
position:absolute;
top:0px;
left:0px;
padding:75px;
line-height:97%;
}
div.center {
text-align:center;
}
div.imageText {
text-shadow:0px 0px 5px rgba(0,0,0,0.2);
}
div.dark-text {
color: #6e6e6e;
}
.leaflet-tutorial {
margin-top: 0px;
padding: 0 0 0 0;
height: 100%;
}
.leaflet-tutorial img {
height: 100%;
width: auto;
}
.leaflet-tutorial pre {
background-color: #222;
}
</style><script type='text/javascript'>
window.onload = function() {
var s = document.getElementsByTagName('div'), ti;
if (!s) return;
big = { current: 0, forward: fwd, reverse: rev, go: go, length: s.length };
function go(n) {
big.current = n;
var i = 1e3, e = s[n], t = parseInt(e.dataset.timeToNext || 0, 10);
document.body.className = e.dataset.bodyclass || '';
for (var k = 0; k < s.length; k++) s[k].style.display = 'none';
e.style.display = 'inline';
e.style.fontSize = i + 'px';
if (e.firstChild && e.firstChild.nodeName === 'IMG') {
document.body.style.backgroundImage = 'url(' + e.firstChild.src + ')';
e.firstChild.style.display = 'none';
if ('classList' in e) e.classList.add('imageText');
} else {
document.body.style.backgroundImage = '';
document.body.style.backgroundColor = e.style.backgroundColor;
}
if (ti !== undefined) window.clearInterval(ti);
if (t > 0) ti = window.setTimeout(fwd, (t * 1000));
while ((e.offsetWidth > window.innerWidth ||
e.offsetHeight > window.innerHeight) && i >= 0) {
e.style.fontSize = (i -= 2) + 'px';
}
e.style.lineHeight = (i + 20) + 'px';
e.style.marginTop = ((window.innerHeight - e.offsetHeight) / 2) + 'px';
if (window.location.hash !== n) window.location.hash = n;
document.title = e.textContent || e.innerText;
}
document.onclick = function() { go(++big.current % (s.length)); };
function fwd() { go(Math.min(s.length - 1, ++big.current)); }
function rev() { go(Math.max(0, --big.current)); }
document.onkeydown = function(e) {
if (e.which === 39 || e.which === 34 || e.which === 40) fwd();
if (e.which === 37 || e.which === 33 || e.which === 38) rev();
};
document.ontouchstart = function(e) {
var x0 = e.changedTouches[0].pageX;
document.ontouchend = function(e) {
var x1 = e.changedTouches[0].pageX;
if (x1 - x0 < 0) fwd();
if (x1 - x0 > 0) rev();
};
};
function parse_hash() {
return Math.max(Math.min(s.length - 1,
parseInt(window.location.hash.substring(1), 10)), 0);
}
if (window.location.hash) big.current = parse_hash() || big.current;
window.onhashchange = function() {
var c = parse_hash();
if (c !== big.current) go(c);
};
go(big.current);
};
</script></head><body>
<div>Web Mapping <em>Fundamentals</em></div>
<div>
url: <a href="http://bit.do/M49S">http://bit.do/M49S</a>
src: <a href="http://bit.do/M49Z">http://bit.do/M49Z</a>
</div>
<div>
<a href="http://maptimeatx.github.io/">http://maptimeatx.github.io/</a>
<a href="http://maptime.io/">http://maptime.io/</a>
</div>
<div>Feel free to ask questions!</div>
<div>What's a Web Map?</div>
<div>It's a Map</div>
<div>But not on paper</div>
<div>And not in a desktop application</div>
<div>On the Internet, accessible via browser</div>
<div>like</div>
<div><img src="img/google-map.png"><a href="http://maps.google.com">GoogleMaps</a></div>
<div><img src="img/bing.png"><a href="http://www.bing.com/maps/">BingMaps</a></div>
<div><img src="img/osm.png"><a href="http://openstreetmap.org">OpenStreetMap</a></div>
<div><img src="img/google-earth.png">Flat, not a digital globe like <a href="https://www.google.com/earth/">Google Earth</a></div>
<div><img src="img/slippy-map.gif">Usually interactive</div>
<div>
Comprised of <em>TILES</em>
<img src="img/tiles.gif">
</div>
<div>Tiles?</div>
<div>
<img src="img/detour1.png">
History Detour
(somewhat accurate)
>>>
</div>
<div>
First there were Desktop Maps like <a href="http://esri.com">esri's</a> ArcView<br>
<img style="width:800px;" src="img/map-history/ArcViewGIS.png">
</div>
<div>
(which was later replaced by ArcMap)<br>
<img style="width:800px;" src="img/map-history/1-arcGIS.jpg">
</div>
<div class="dark-text"><img src="img/map-history/2-Ridgefield-CT-Mapquest-out.jpg">In 1996 <a href="http://mapquest.com">MapQuest</a> launched their web service</div>
<div>Directions! Online! Whoa!</div>
<div>But it was pretty <em>slow</em>, required <em>full page reloads</em> to scroll or zoom, and was aligned to <em>specific boundaries</em></div>
<div>In 2005 <a href="http://maps.google.com">Google Maps</a> <em>changed</em> the game</div>
<div><img src="img/map-history/3-old-google-maps-1.JPG">Smooth scrolling & zooming</div>
<div>What was the big change?</div>
<div>
It was the <em>TILE</em>
<img src="img/tiles.gif">
</div>
<div>
End of Detour
<img src="img/end-detour.png">
</div>
<div>So what's so special about <em>tiles</em>?</div>
<div>An image for the entire world at multiple scales would be <em>HUGE</em></div>
<div>Tiles are <em>small</em> 256x256-pixel images placed next to each other to look like one <em>large</em> image</div>
<div><img src="img/tiles-loading.gif">All these little tiles load <em>way faster</em> than one big map</div>
<div>Different <em>zoom levels</em> for different amounts of <em>detail</em></div>
<div>Tiles are arranged in a <em>grid</em> for each <em>zoom level</em></div>
<div class="dark-text"><img src="img/tiles/zoom0.png">Zoom level 0:<br> <em>one</em> tile for the world</div>
<div>With each additional zoom level, the number of tiles increases <em>exponentially</em>.</div>
<div class="dark-text"><img src="img/tiles/zoom1.png">Zoom level 1:<br> <em>4 tiles</em> for the world</div>
<div><img src="img/tiles/zoom1.png"></div>
<div>Zoom level 2: <em>16 tiles</em><br>Zoom level 3: <em>64 tiles</em></div>
<div><img src="img/tiles/zoom2-3-4-5.png"></div>
<div><img src="img/tiles/zoom13.png">Zoom level 13:<br> <em>67,108,864 tiles</em></div>
<div>Map tiles are just images on the web, so you can link to them individually</div>
<div>For example: <a href="http://tile.openstreetmap.org/4/2/6.png">http://tile.openstreetmap.org/4/2/6.png</a></div>
<div>In order to understand how this works, let's break down the URL</div>
<div>http://<em>tile.openstreetmap.org</em>/4/2/6.png -- this is the name of the tile server</div>
<div>http://tile.openstreetmap.org/<em>4</em>/2/6.png -- this is the <em>z</em> value, or the <em>zoom level</em></div>
<div>http://tile.openstreetmap.org/4/<em>2/6</em>.png -- This is the <em>x/y</em> value, or the place in the grid where the tile lives</div>
<div>All tiles have the same boundaries<img src="img/tiles.gif"></div>
<div><em>Mapping Libraries</em> do the work of positioning the tiles for you and handling interactions</div>
<div>There are many, such as <a href="https://developers.google.com/maps/web/">Google Maps API</a>, <a href="https://developers.arcgis.com/javascript/">Esri Javascript API</a>, <a href="http://openlayers.org/">OpenLayers</a></div>
<div><img src="img/leaflet.png"><a href="http://leafletjs.com">Leaflet</a></div>
<div>Web maps use the <em>Mercator projection</em>, which was designed for sailors BUT works well for flat maps</div>
<div><a href="http://commons.wikimedia.org/wiki/File:1855_Colton_Map_of_the_World_on_Mercator_Projection_-_Geographicus_-_WorldMercator-colton-1855.jpg"><img src="img/mercator.jpg"></a></div>
<div>
<img src="img/detour1.png">
Projection Detour
</div>
<div>The Earth is <em>Round</em></div>
<div>A Map is <em>Flat</em></div>
<div>A sphere's surface cannot be represented on a plane without distortion - Gauss</div>
<div>Mercator is <em>conformal</em> - preserves direction, but clobbers area</div>
<div><img src="img/mercator2.jpg">Constant direction as straight line</div>
<div>
<img style="width:100%;" src="img/Tissot_mercator.png">
Image by <a href="http://en.wikipedia.org/wiki/Mercator_projection#mediaviewer/File:Tissot_mercator.png">Stefan Kuhn</a>
</div>
<div>Because of how web maps are used, Mercator is a good choice of projection</div>
<div>Otherwise the angles of your streets would be all <em>goofy</em></div>
<div>(Actually a special Google-developed type of Mercator called 'Web Mercator' is used)</div>
<div>
End of Detour
<img src="img/end-detour.png">
</div>
<div>So we have tiles which usually form a <em>Base Layer</em></div>
<div>We can also have <em>Vectors</em>!</div>
<div>Points, lines, polygons</div>
<div>OH MY</div>
<div>Vectors are drawn on top of the tiles and add <em>interaction</em></div>
<div><img src="img/vectors.png"></div>
<div>Wrapping up:</div>
<div><em>Tiles</em> - images that make the map</div>
<div><em>Vectors</em> - graphics on top of the map</div>
<div><em>Mapping Library</em> - code that positions the tiles and draws the vectors</div>
<div>All in your <em>Web Browser</em></div>
<div>Sweet!</div>
<div>
Credits:
<ul>
<li><a href="https://github.com/maptime/anatomy-of-a-web-map">github.com/maptime/anatomy-of-a-web-map</a></li>
<li><a href="https://www.mapbox.com/foundations/how-web-maps-work/">https://www.mapbox.com/foundations/how-web-maps-work/</a></li>
</ul>
</div>
<div><img src="img/leaflet_code.png">Let's Make a Map!</div>
<div>To start us off: <a href="http://bit.do/M7Aj">http://bit.do/M7Aj</a></div>
<div class="leaflet-tutorial">
<img src=img/leaflet-hands-on/base.png>
</div>
<div class="leaflet-tutorial">
<img src=img/leaflet-hands-on/doctype.png>
</div>
<div class="leaflet-tutorial">
<img src=img/leaflet-hands-on/html.png>
</div>
<div class="leaflet-tutorial">
<img src=img/leaflet-hands-on/head.png>
</div>
<div class="leaflet-tutorial">
<img src=img/leaflet-hands-on/body.png>
</div>
<div class="leaflet-tutorial">
<img src=img/leaflet-hands-on/body-and-maps.png>
</div>
<div class="leaflet-tutorial">
<img src=img/leaflet-hands-on/leaflet-css.png>
</div>
<div class="leaflet-tutorial">
<img src=img/leaflet-hands-on/custom-style.png>
</div>
<div class="leaflet-tutorial">
<img src=img/leaflet-hands-on/leaflet-js.png>
</div>
<div class="leaflet-tutorial">
<img src=img/leaflet-hands-on/map-div.png>
</div>
<div class="leaflet-tutorial">
<img src=img/leaflet-hands-on/custom-script.png>
</div>
<div>
Let's start writing that.
</div>
<div class="leaflet-tutorial">
<pre>
var ourMap = L.map('map');</pre>
</div>
<div class="leaflet-tutorial">
<pre>
var ourMap = <em>L.map(</em>'map'<em>)</em>;</pre>
Create a Leaflet map.
</div>
<div class="leaflet-tutorial">
<pre>
var ourMap = L.map(<em>'map'</em>);</pre>
At the element with id="map".
</div>
<div class="leaflet-tutorial">
<pre>
<em>var ourMap =</em> L.map('map');</pre>
And store the map as a variable called ourMap.
</div>
<div class="leaflet-tutorial">
<pre>
var baseLayer = L.tileLayer(
'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
);</pre>
</div>
<div class="leaflet-tutorial">
<pre>
var baseLayer = <em>L.tileLayer(</em>
'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
<em>)</em>;</pre>
Create a tile layer.
</div>
<div class="leaflet-tutorial">
<pre>
var baseLayer = L.tileLayer(
<em>'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'</em>
);</pre>
We'll use basic OpenStreetMap tiles. This string is a template for how Leaflet will ask for tiles from a server.
</div>
<div class="leaflet-tutorial">
<pre>
var baseLayer = L.tileLayer(
'http://{s}.tile.openstreetmap.org/<em>{z}</em>/<em>{x}</em>/<em>{y}</em>.png'
);</pre>
These are placeholders for the tile <em>z</em>, <em>x</em>, and <em>y</em> coordinates we talked about a while ago. Leaflet will replace these with real values when you pan/zoom around.
</div>
<div class="leaflet-tutorial">
<pre>
var baseLayer = L.tileLayer(
'http://<em>{s}</em>.tile.openstreetmap.org/{z}/{x}/{y}.png'
);</pre>
This is another placeholder. It gets replaced with letters (a, b, c, d). This spreads the image requests across a few domains so the tiles can load faster.
</div>
<div class="leaflet-tutorial">
<pre>
<em>var baseLayer</em> = L.tileLayer(
'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
);</pre>
Store this tile layer as a variable called baseLayer.
</div>
<div class="leaflet-tutorial">
<pre><em>baseLayer</em>.addTo(ourMap);</pre>
Take that <em>base layer</em> and add it to our map.
</div>
<div class="leaflet-tutorial">
<pre>baseLayer.<em>addTo(</em>ourMap<em>)</em>;</pre>
Take that base layer and <em>add it to</em> our map.
</div>
<div class="leaflet-tutorial">
<pre>baseLayer.addTo(<em>ourMap</em>);</pre>
Take that base layer and add it to <em>our map</em>.
</div>
<div class="leaflet-tutorial">
<pre><em>ourMap</em>.setView([30.3, -97.7], 10);</pre>
Take <em>our map</em> and set the view area to be centered on Austin with zoom level 10.
</div>
<div class="leaflet-tutorial">
<pre>ourMap.<em>setView(</em>[30.3, -97.7], 10<em>)</em>;</pre>
Take our map and <em>set the view area</em> to be centered on Austin with zoom level 10.
</div>
<div class="leaflet-tutorial">
<pre>ourMap.setView(<em>[30.3, -97.7]</em>, 10);</pre>
Take our map and set the view area to be <em>centered on Austin</em> with zoom level 10.
</div>
<div class="leaflet-tutorial">
<pre>ourMap.setView([<em>30.3</em>, -97.7], 10);</pre>
<em>
Latitude.
</em>
</div>
<div class="leaflet-tutorial">
<pre>ourMap.setView([30.3, <em>-97.7</em>], 10);</pre>
<em>
Longitude.
</em>
</div>
<div class="leaflet-tutorial">
<pre>ourMap.setView([30.3, -97.7], <em>10</em>);</pre>
Take our map and set the view area to be centered on Austin with <em>zoom level 10</em>.
</div>
<div>
Add points on the map?
</div>
<div class="leaflet-tutorial">
<pre>var ourMarker = <em>L.marker(</em>[30.27, -97.741]<em>)</em>;</pre>
Create a <em>marker</em>. That's what points on the map are called.
</div>
<div class="leaflet-tutorial">
<pre>var ourMarker = L.marker([<em>30.27</em>, -97.741]);</pre>
<em>
Latitude.
</em>
</div>
<div class="leaflet-tutorial">
<pre>var ourMarker = L.marker([30.27, <em>-97.741</em>]);</pre>
<em>
Longitude.
</em>
</div>
<div class="leaflet-tutorial">
<pre><em>var ourMarker</em> = L.marker([30.27, -97.741]);</pre>
Store it as a variable called <em>ourMarker</em>
</div>
<div class="leaflet-tutorial">
<pre>var ourMarker = L.marker([30.27, -97.741]);
<em>ourMarker</em>.addTo(ourMap);</pre>
<em>Take our marker</em> and add it to our map.
</div>
<div class="leaflet-tutorial">
<pre>var ourMarker = L.marker([30.27, -97.741]);
ourMarker.<em>addTo(</em>ourMap<em>)</em>;</pre>
Take our marker <em>and add it</em> to our map.
</div>
<div class="leaflet-tutorial">
<pre>var ourMarker = L.marker([30.27, -97.741]);
ourMarker.addTo(<em>ourMap</em>);</pre>
Take our marker and add it <em>to our map</em>.
</div>
<div>
Popup text!
</div>
<div class="leaflet-tutorial">
<pre>var ourMarker = L.marker([30.27, -97.741]);
ourMarker.addTo(ourMap);
<em>ourMarker</em>.bindPopup('#maptimeATX');</pre>
Take <em>our marker</em> and bind some popup text to it.
</div>
<div class="leaflet-tutorial">
<pre>var ourMarker = L.marker([30.27, -97.741]);
ourMarker.addTo(ourMap);
ourMarker.<em>bindPopup(</em>'#maptimeATX'<em>)</em>;</pre>
Take our marker and <em>bind</em> some popup text to it.
</div>
<div class="leaflet-tutorial">
<pre>var ourMarker = L.marker([30.27, -97.741]);
ourMarker.addTo(ourMap);
ourMarker.bindPopup(<em>'#maptimeATX'</em>);</pre>
Take our marker and bind some <em>popup text</em> to it.
</div>
<div>
All together now.
</div>
<div class="leaflet-tutorial">
<pre>
var ourMap = L.map('map');
var baseLayer = L.tileLayer(
'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
);
baseLayer.addTo(ourMap);
ourMap.setView([30.3, -97.7], 10);
var ourMarker = L.marker([30.27, -97.741]);
ourMarker.addTo(ourMap);
ourMarker.bindPopup('#maptimeATX');</pre>
Add your own markers. Or whatever you want. Have fun.
</div>
<div>
Thanks!
</div>
</body></html>