forked from zenorocha/diveintohtml5
-
Notifications
You must be signed in to change notification settings - Fork 6
/
geolocation.html
976 lines (938 loc) · 39.1 KB
/
geolocation.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
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
---
title: Geolocalização - Dive Into HTML5
---
<!DOCTYPE html>
<html
lang="pt-br"
class=" js flexbox canvas canvastext webgl no-touch geolocation postmessage websqldatabase no-indexeddb hashchange history draganddrop websockets rgba hsla multiplebgs backgroundsize borderimage borderradius boxshadow textshadow opacity cssanimations csscolumns cssgradients cssreflections csstransforms csstransforms3d csstransitions fontface video audio localstorage sessionstorage webworkers applicationcache svg inlinesvg smil svgclippaths"
>
<head>
<meta charset="utf-8" />
<title>{{ page.title }}</title>
<!--[if lt IE 9]><script src=j/html5.js></script><![endif]-->
<link
rel="alternate"
type="application/atom+xml"
href="https://github.com/webfatorial/diveintohtml5/commits/gh-pages.atom"
/>
<link
rel="alternate"
href="http://diveintohtml5.info/geolocation.html"
hreflang="en"
/>
<link rel="stylesheet" href="screen.css" />
<style>
body {
counter-reset: h1 6;
}
</style>
<link
rel="stylesheet"
media="only screen and (max-device-width: 480px)"
href="mobile.css"
/>
<link rel="prefetch" href="index.html" />
<script
type="text/javascript"
charset="UTF-8"
src="https://maps.googleapis.com/maps-api-v3/api/js/38/5/common.js"
></script>
<script
type="text/javascript"
charset="UTF-8"
src="https://maps.googleapis.com/maps-api-v3/api/js/38/5/util.js"
></script>
</head>
<body cz-shortcut-listen="true">
{% include fork.html %}
<p>
Você está aqui: <a href="index.html">Home</a> <span class="u">‣</span>
<a href="table-of-contents.html#geolocation"
>Dive Into <abbr>HTML5</abbr></a
>
<span class="u">‣</span>
</p>
<h1><br />Você Está Aqui<br />(Assim Como Todo Mundo Está)</h1>
<p id="toc"><a href="javascript:showTOC()">exibir índice analítico</a></p>
<p class="a">❧</p>
<h2 id="divingin">Mergulhando</h2>
<p class="f">
<img src="i/aoc-g.png" alt="G" width="106" height="103" />eolocalização é
a arte de descobrir aonde você está no mundo e (opcionalmente)
compartilhar essa informação com as pessoas que você confia. Há mais de
uma maneira de descobrir aonde você está — seu endereço <abbr>IP</abbr>,
sua conexão de rede sem fio, com que torre de celular seu telefone está
falando, ou hardware <abbr>GPS</abbr> dedicado que calcula latitude e
longitude da informação enviada por satélites no céu.
</p>
<div class="pf">
<h4>Pergunte ao Professor Marcação</h4>
<div class="inner">
<blockquote class="note">
<p>
<span>☞</span>P: Geolocalização parece assustador. Posso
desligá-la?<br />
R: Privacidade é uma preocupação óbvia quando se está falando sobre
compartilhar sua localização física com um servidor web remoto. A
<a href="http://www.w3.org/TR/geolocation-API/#security"
><abbr>API</abbr> de geolocalização diz explicitamente</a
>: “User Agents não devem enviar informação de localização para
sites na Web sem a expressa permissão do usuário.” Em outras
palavras, compartilhar a sua localização é sempre opcional. Se você
não quiser, você não tem que fazê-lo.
</p>
</blockquote>
</div>
</div>
<p class="a">❧</p>
<h2 id="w3c">API de geolocalização</h2>
<p>
A
<a href="http://www.w3.org/TR/geolocation-API/"
><abbr>API</abbr> de geolocalização</a
>
permite que você compartilhe sua localização em sites confiáveis. A
latitude e longitude são disponibilizadas na página via JavaScript, que
por sua vez pode ser enviado a um servidor web e fazer coisas como
encontrar locais ao seu redor ou mostrar sua posição em um mapa.
</p>
<p>
Como você pode ver na tabela a seguir, a <abbr>API</abbr> de
geolocalização é suportada pela maioria dos navegadores desktop e
dispositivos móveis. Além disso, vários navegadores e dispositivos antigos
podem oferecer suporte via bibliotecas de terceiros, como veremos depois
neste capítulo.
</p>
<table class="bc">
<caption>
Suporte da
<abbr>API</abbr>
de geolocalização
</caption>
<thead>
<tr>
<th title="Internet Explorer">IE</th>
<th title="Mozilla Firefox">Firefox</th>
<th title="Apple Safari">Safari</th>
<th title="Google Chrome">Chrome</th>
<th>Opera</th>
<th>iPhone</th>
<th>Android</th>
</tr>
</thead>
<tbody>
<tr>
<td>9.0+</td>
<td>3.5+</td>
<td>5.0+</td>
<td>5.0+</td>
<td>10.6+</td>
<td>3.0+</td>
<td>2.0+</td>
</tr>
</tbody>
</table>
<p>
Junto com o suporte padrão da <abbr>API</abbr> de geolocalização, há
tambem várias <abbr>API</abbr>s de dispositivos específicos em outras
plataformas móveis. Falarei sobre tudo isso ainda neste capítulo.
</p>
<p class="a">❧</p>
<h2 id="the-code">Mostre-me o código</h2>
<p>
A <abbr>API</abbr> de geolocalização centraliza tudo em volta da sua nova
propriedade global chamada <code>navigator</code> com o objeto:
<code>navigator.geolocation</code>.
</p>
<p>
O simples uso da <abbr>API</abbr> de geolocalização se parece com isso:
</p>
<pre><code>function get_location() {
<mark>navigator.geolocation.getCurrentPosition</mark>(show_map);
}</code></pre>
<p>
Porém isso não detecta o posicionamento (latitude e longitude), não há
tratamento de erros e não retorna opções. Você pode incluir uma
verificação para detectar se há suporte para a <abbr>API</abbr> de
geolocalização. Para
<a href="detect.html#geolocation">detectar se há suporte</a>, você pode
usar o <a href="http://www.modernizr.com/">Modernizr</a>:
</p>
<pre style="float:left;padding-left:0"><code>function get_location() {
if (<mark>Modernizr.geolocation</mark>) {
navigator.geolocation.getCurrentPosition(show_map);
} else {
// no native support; maybe try Gears?
}
}</code></pre>
<p class="legend right" style="margin-top:2.5em">
<span class="arrow"> ⇜</span> EU POSSO TER GEOLOCALIZAÇÃO?
</p>
<p class="clear">
O que você faz sem o suporte da geolocalização é contigo. Eu explicarei
como fazer um fallback em um minuto, mas antes eu quero falar sobre o que
acontecerá <em>durante</em> a chamada do método
<code>getCurrentPosition()</code>. Como
<a href="#divingin">eu mencionei no começo deste capítulo</a>, o suporte
da geolocalização é <em>opcional</em>. Isso significa que seu browser
nunca irá forçar você revelar sua localização física atual para um
servidor remoto. A experiência do usuário é diferente de browser pra
browser. No Mozilla Firefox, a chamada do método
<code>getCurrentPosition()</code> da <abbr>API</abbr> de geolocalização
fará com que o browser mostre uma “barra de notificação” no topo da janela
do navegador. Essa barra se parece com isso:
</p>
<p class="c">
<img
src="i/geolocation-opt-in.png"
alt="Geolocation opt-in infobar"
width="737"
height="32"
/>
</p>
<p>Há muita coisa acontecendo aqui. Você, como um usuário final,</p>
<ul>
<li>é dito que um site pergunta sua localização</li>
<li>é dito <em>qual</em> o site que pergunta sua localização</li>
<li>
em
<a href="http://www.mozilla.com/en-US/firefox/geolocation/"
>Mozilla’s “Location-Aware Browsing”</a
>
explicará que diabos está acontecendo (lembre-se: o Google fornece sua
localização e salva seus dados de acordo com sua
<a href="http://www.google.com/intl/en/privacy/lsf.html"
>Política de Privacidade sobre Serviços de Localização</a
>)
</li>
<li>pode escolher para compartilhar sua localização</li>
<li>pode escolher para <em>não</em> compartilhar sua localização</li>
<li>
pode falar pro seu browser para lembrar sua escolha (espera aí,
compartilhar ou não compartilhar sua localização) então você nunca mais
verá está barra de notificação novamente neste site
</li>
</ul>
<p>Além disso, essa barra é</p>
<ul>
<li>
não modal, então não irá impedí-lo de mudar para uma outra janela ou tab
</li>
<li>
tab específica, irá desaparecer se você mudar para uma outra janela ou
tab e reaparecerá quando você voltar para a janela ou tab em que estava
</li>
<li>
incondicional, então não há como um site roubar sua localização sem sua
permissão
</li>
<li>
segura, não há chance de um site poder determinar sua localização
enquanto ele estiver esperando sua resposta
</li>
</ul>
<p>
Você acabou de ver o código em JavaScript com que fez essa barra de
notificação aparecer. É uma chamada de função única que tem uma função de
callback (no qual chamei de <code>show_map</code>). A chamada do método
<code>getCurrentPosition()</code> retornará a localização imediatamente,
mas isso não quer dizer que você terá a localização do usuário. O primeiro
lugar que é garantido para você o acesso a localização do usuário é na
função de callback. A função de callback se parece com isso:
</p>
<pre><code>function show_map(position) {
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
// let's show a map or do something interesting!
}</code></pre>
<p>
A função de callback será chamada com um único parâmetro, e retornará um
objeto com duas propriedades: <code>coords</code> e
<code>timestamp</code>. O timestamp é somente a data e o horário de quando
a localização foi calculada. (Uma vez que tudo isso está acontecendo de
forma assíncrona, você poderá realmente não saber quando irá acontecer com
antecedência. Pode demorar algum tempo para que o usuário visualize a
barra de notificação e aceite compartilhar sua localização. Dispositivos
com <abbr>GPS</abbr> dedicado podem demorar mais tempo para se conectar
com o satélite do <abbr>GPS</abbr>. E assim por diante.) O objeto
<code>coords</code> possui propriedades como <code>latitude</code> e
<code>longitude</code> que são exatamente o que parece ser: a localização
física do usuário no mundo.
</p>
<table class="st">
<caption>
Posição do Objeto
</caption>
<tbody>
<tr class="ho">
<th>Propriedade</th>
<th>Tipo</th>
<th>Observação</th>
</tr>
<tr class="zebra">
<th><code>coords.latitude</code></th>
<td>double</td>
<td>graus decimais</td>
</tr>
<tr>
<th><code>coords.longitude</code></th>
<td>double</td>
<td>graus decimais</td>
</tr>
<tr class="zebra">
<th><code>coords.altitude</code></th>
<td>double ou <code>null</code></td>
<td>
metros em
<a href="http://en.wikipedia.org/wiki/Reference_ellipsoid"
>elipsoide de referência</a
>
</td>
</tr>
<tr>
<th><code>coords.accuracy</code></th>
<td>double</td>
<td>metros</td>
</tr>
<tr class="zebra">
<th><code>coords.altitudeAccuracy</code></th>
<td>double ou <code>null</code></td>
<td>metros</td>
</tr>
<tr>
<th><code>coords.heading</code></th>
<td>double ou <code>null</code></td>
<td>
graus em sentido do
<a href="http://en.wikipedia.org/wiki/True_north"
>norte verdadeiro</a
>
</td>
</tr>
<tr class="zebra">
<th><code>coords.speed</code></th>
<td>double ou <code>null</code></td>
<td>metros/segundos</td>
</tr>
<tr>
<th><code>timestamp</code></th>
<td>DOMTimeStamp</td>
<td>como um objeto de <code>Date()</code></td>
</tr>
</tbody>
</table>
<p class="ss" style="margin-top:1.75em">
<img
src="i/openclipart.org_johnny_automatic_riding_a_bike.png"
width="196"
height="239"
alt="boy riding a bicycle"
/>
</p>
<p>
Somente três de uma das propriedades são garantidas
(<code>coords.latitude</code>, <code>coords.longitude</code>, e
<code>coords.accuracy</code>). O restante pode voltar <code>null</code>,
dependendo da capacidade do seu dispositivo e a distância que o servidor
está de você. As propriedades <code>heading</code> e
<code>speed</code> serão calculadas baseadas na posição anterior do
usuário, se possível.
</p>
<p class="a">❧</p>
<h2 id="errors">Lidando com erros</h2>
<p>
Geolocalização é complicado. Coisas podem dar errado. Eu havia dito que o
“consentimento do usuário” é estranho. Se sua aplicação precisa da
localização do usuário mas o usuário não permitir, você está ferrado. O
usuário sempre ganha. Se ele não permitir, o que apareceria como mensagem?
Veja o segundo parâmetro do método <code>getCurrentPosition()</code>: um
erro é chamado na função de callback.
</p>
<pre><code>navigator.geolocation.getCurrentPosition(
show_map, <mark>handle_error</mark>)</code></pre>
<p>
Se qualquer coisa sair errado, sua função callback de erro será chamada
com um objeto <code>PositionError</code>.
</p>
<table class="st">
<caption>
Objeto PositionError
</caption>
<tbody>
<tr class="ho">
<th>Propriedade</th>
<th>Tipo</th>
<th>Observações</th>
</tr>
<tr class="zebra">
<th><code>code</code></th>
<td>short</td>
<td>um valor enumerado</td>
</tr>
<tr>
<th><code>message</code></th>
<td>DOMString</td>
<td>não usado para usuários finais</td>
</tr>
</tbody>
</table>
<p>A propriedade <code>code</code> retornará um desses resultados</p>
<ul>
<li>
<code>PERMISSION_DENIED</code> (<code>1</code>) se o usuário clicar em
“não compartilhar” ou qualquer outra coisa que bloqueará seu acesso e
sua localização.
</li>
<li>
<code>POSITION_UNAVAILABLE</code> (<code>2</code>) se a rede cair ou a
posição do satélite não poder ser resgatada.
</li>
<li>
<code>TIMEOUT</code> (<code>3</code>) se a rede não cair mas o tempo
para calcular a posição do usuário for longo demais. Como saber o que é
“longo demais”? Vou mostrar como definir isso numa próxima seção.
</li>
</ul>
<p class="legend top" style="padding-left:8.5em">
<span class="arrow">↶</span> Seja educado na derrota
</p>
<pre><code>function handle_error(err) {
if (<mark>err.code</mark> == 1) {
// user said no!
}
}</code></pre>
<div class="pf">
<h4>Pergunte ao professor marcação</h4>
<div class="inner">
<blockquote class="note">
<p>
<span>☞</span>P: A <abbr>API</abbr> de geolocalização pega na
Estação Espacial Internacional, na Lua, ou em outros planetas?<br />
R:
<a
href="http://www.w3.org/TR/geolocation-API/#coordinates_interface"
>Os estados específicos da geolocalização</a
>, “O sistema de referência geográfica de coordenadas usado pelos
atributos é referente ao World Geodetic System (2d) [WGS84]. Nenhum
outro sistema de referência é suportado.” A Estação Espacial
Internacional está em órbita na Terra, então os
<a href="http://twitter.com/Astro_TJ">astronautas na estacão</a>
podem dizer suas localizações por latitude, longitude e altitude. No
entanto, o World Geodetic System é centralizado somente na Terra,
por isso não podemos usar para saber localizações na Lua ou em
outros planetas.
</p>
</blockquote>
</div>
</div>
<p class="a">❧</p>
<h2 id="options">Escolhas! Eu quero escolhas!</h2>
<p>
Alguns aparelhos — como iPhone e Android — suportam <em>dois</em> métodos
para mostrar sua localização. O primeiro método triangula a sua posição
baseando-se na sua localização relativa das diferentes torres da sua
operadora de celular. Este método é rápido e não necessita de qualquer
hardware de <abbr>GPS</abbr> dedicado, mas ele só pega uma ideia
aproximada de onde você está.
</p>
<p style="float:left;margin:1.75em 1.75em 1.75em 0">
<img
src="i/openclipart.org_johnny_automatic_young_girl_pointing.png"
alt="young girl pointing"
width="336"
height="229"
/>
</p>
<p>
O segundo método atualmente usa algum hardware de
<abbr>GPS</abbr> dedicado em seu aparelho para se comunicar com algum
satélite de <abbr>GPS</abbr> dedicado que está orbitando na Terra. O
<abbr>GPS</abbr> normalmente pode identificar a sua localização a poucos
metros. O lado negativo de um chip de <abbr>GPS</abbr> dedicado em seu
aparelho é que consome muita energia, então telefones e outros
dispositivos geralmente desligam esse chip quando precisa. Isso significa
que terá um atraso quando o chip for inicializado para se conectar com o
satélite. Se você sempre usa o Google Maps em um iPhone ou outro
smartphone, você já viu os dois métodos em ação. Primeiro você vê um
grande círculo que aproxima sua posição (procurando uma torre de celular
próxima), então um círculo menor (triangulando com outras torres de
celulares), então um único ponto com sua posição exata (pego por um
satélite de <abbr>GPS</abbr>).
</p>
<p>
A razão de eu falar isso é que, dependendo da sua aplicação web, você
talvez não terá uma grande precisão. Se você estiver somente procurando
por alguns cinemas nas proximidades, uma precisão menor provavelmente será
o suficiente pra você. Não há muitas salas de cinema, mesmo em cidades
maiores, e você provavelmente vai listar mais de uma. Por outro lado, se
voce está querendo direções em tempo real, você realmente terá que saber
onde o usuário está exatamente para poder dizer “vire à direita em 20
metros” ou qualquer outra coisa.
</p>
<p>
O método <code>getCurrentPosition()</code> tem como um terceiro argumento
opcional,
<a href="http://www.w3.org/TR/geolocation-API/#position-options"
>um objeto <code>PositionOptions</code></a
>. Existem três propriedades que você pode definir no objeto
<code>PositionOptions</code>. Todas as propriedades são opcionais. Você
pode definir qualquer uma ou todas, ou nenhuma delas.
</p>
<table class="st">
<caption>
Objeto PositionOptions
</caption>
<tbody>
<tr class="ho">
<th>Propriedade</th>
<th>Tipo</th>
<th>Padrão</th>
<th>Observações</th>
</tr>
<tr class="zebra">
<th><code>enableHighAccuracy</code></th>
<td>Booleano</td>
<td>false</td>
<td>true pode ser mais lento</td>
</tr>
<tr>
<th><code>timeout</code></th>
<td>long</td>
<td>(sem padrão)</td>
<td>em millisegundos</td>
</tr>
<tr class="zebra">
<th><code>maximumAge</code></th>
<td>long</td>
<td>0</td>
<td>em millisegundos</td>
</tr>
</tbody>
</table>
<p>
A propriedade <code>enableHighAccuracy</code> é exatamente o que se
parece. Se for verdadeiro, e o dispositivo tiver suporte para tal, e o
usuário permitir compartilhar sua posição, então o dispositivo irá tentar
fornecer uma precisão maior. Tanto iPhones quanto Androids tem uma
permissão separada para baixa e alta precisão, por isso, é possível que a
chamada <code>getCurrentPosition()</code> com
<code>enableHighAccuracy:true</code> possa falhar, mas chamar com
<code>enableHighAccuracy:false</code> poderá dar certo.
</p>
<p>
A propriedade <code>timeout</code> é um número em millisegundos que sua
aplicação irá esperar pela posição. Este tempo não será contado
<em>antes</em> do usuário dar permissão para tentar calcular sua posição.
Não é o tempo do usuário; é o tempo da rede.
</p>
<p>
A propriedade <code>maximumAge</code> permite que os dispositivos
respondam imediatamente com uma posição em cache. Por exemplo, vamos
chamar o método <code>getCurrentPosition()</code> por um período, o
usuário permitiu, e a função de callback chamou a posição que foi
calculada exatamente às 10:00 horas da manhã, você chamou o método
<code>getCurrentPosition()</code> novamente com a propriedade
<code>maximumAge</code> em <code>75000</code>.
</p>
<pre><code>navigator.geolocation.getCurrentPosition(
success_callback, error_callback, <mark>{maximumAge: 75000}</mark>);</code></pre>
<p>
O que você está dizendo é que você não precisa necessariamente da posição
atual do usuário. Você provavelmente ficará satisfeito sabendo onde ele
esteve em 75 segundos atrás (75000 millisegundos). O dispositivo sabe onde
o usuário foi em 60 segundos atrás (60000 millisegundos), porque sua
posição foi calculada antes da primeira chamada do método
<code>getCurrentPosition()</code>. Então o dispositivo não precisa
recalcular o localização do usuário novamente. Ele somente retorna
exatamente a mesma informação que foi retornada na primeira chamada: mesma
latitude, mesma longitude, mesma precisão, e mesmo timestamp (10:00 da
manhã).
</p>
<p class="ss">
<img
src="i/openclipart.org_maven_Galileo_Galilei.png"
alt="velho homem olhando em seu telescópio"
width="208"
height="508"
/>
</p>
<p>
Antes que você pergunte pela localização do usuário, deve-se pensar sobre
o quanto de precisão você precisa, e definir
<code>enableHighAccuracy</code> de acordo. Se você precisa encontrar sua
localização mais de uma vez, você deve pensar sobre como uma informação
antiga pode vir ser útil, e definir <code>maximumAge</code> de acordo. Se
você precisa encontrar sua localização <em>continuamente</em>, então o
método <code>getCurrentPosition()</code> não é pra você. Você precisa
utilizar o método <code>watchPosition()</code>.
</p>
<p>
O método <code>watchPosition()</code> tem a mesma estrutura que o método
<code>getCurrentPosition()</code>. Tem duas funcões de callback, uma
necessária para sucesso e uma opcional para qualquer erro que possa dar, e
também pode ter um objeto opcional <code>PositionOptions</code> que terá
todas as mesmas propriedades que você aprendeu. A diferença é que sua
função de callback irá ser chamada
<em>toda vez que a localização do usuário mudar</em>. Não há necessidade
de pesquisar sua posição toda hora. O dispositivo irá determinar o melhor
intervalo pra pesquisa da localização, e ele irá chamar sua função de
callback sempre que a posição do usuário alterar. Você pode usar isto para
atualizar um marcador em um mapa, fornecendo instruções sobre onde deve
ir, ou o que quiser.
</p>
<p>
O método <code>watchPosition()</code> retornará sempre um número. Você
provavelmente deve guardar este número em algum lugar. Se você quiser
parar de ver a mudança de localização do usuário, você pode chamar o
método <code>clearWatch()</code> e passar este número, e o dispositivo irá
parar de chamar a funcão de callback. Isso funciona de forma parecida com
as funções Javascript <code>setInterval()</code> e
<code>clearInterval()</code>.
</p>
<p class="a">❧</p>
<h2 id="ie">E o IE?</h2>
<p>
Antes da versão 9 (tecnicamente 9.0RC1), o Internet Explorer não tem
suporte para a
<a href="#w3c"><abbr>API</abbr> de geolocalização da <abbr>W3C</abbr></a
>. Mas não se desespere!
<a href="http://tools.google.com/gears/">Gears</a> é um plugin de código
aberto da Google que funciona em Windows, Mac, Linux, Windows Mobile, e
Android, que fornece recursos para os navegadores antigos. Um desses
recursos que o Gears fornece é a <abbr>API</abbr> de geolocalização. Ele
não é bem a <abbr>API</abbr> de geolocalização da <abbr>W3C</abbr>, mas
tem o mesmo resultado.
</p>
<p>
Enquanto estamos em um assunto de plataformas legadas, gostaria de deixar
bem claro que as plataformas antigas tem suas próprias <abbr>API</abbr>s
de geoloalização.
<a
href="http://www.tonybunce.com/2008/05/08/Blackberry-Browser-Amp-GPS.aspx"
>BlackBerry</a
>,
<a
href="http://www.forum.nokia.com/infocenter/index.jsp?topic=/Web_Developers_Library/GUID-4DDE31C7-EC0D-4EEC-BC3A-A0B0351154F8.html"
>Nokia</a
>,
<a
href="http://developer.palm.com/index.php?option=com_content&view=article&id=1673#GPS-getCurrentPosition"
>Palm</a
>, e
<a href="http://bondi.omtp.org/1.0/apis/geolocation.html"
><abbr title="Open Mobile Terminal Platform">OMTP</abbr> BONDI</a
>
todas fornecem suas próprias <abbr>API</abbr>s. É claro, todas elas
trabalham de forma diferente do Gears, que por sua vez funciona de forma
diferente da <abbr>API</abbr> de geolocalização da <abbr>W3C</abbr>.
Wheeeeee!
</p>
<p class="a">❧</p>
<h2 id="geo-js">geo.js ao resgate</h2>
<p>
<a href="http://code.google.com/p/geo-location-javascript/"
><code>geo.js</code></a
>
é uma biblioteca JavaScript, de código aberto, com licença
<abbr>MIT</abbr> que facilita o uso entre as diferentes
<abbr>APIs</abbr> de geolocalização da <abbr>W3C</abbr>, a Gears
<abbr>API</abbr>, e as <abbr>API</abbr>s fornecidas pela próprias
plataformas. Para usá-la, você irá precisar adicionar dois scripts no
rodapé da sua página. (Tecnicamente, você poderia colocar eles em qualquer
lugar, mas scripts no <code><head></code> vão fazer com que sua
página carregue mais devagar. Então, não faça isso!)
</p>
<p>
O primeiro script é o
<a href="http://code.google.com/apis/gears/gears_init.js"
><code>gears_init.js</code></a
>, que inicializará o Gears caso estiver instalado. O segundo script é o
<a
href="http://geo-location-javascript.googlecode.com/svn/trunk/js/geo.js"
><code>geo.js</code></a
>.
</p>
<pre style="float:left"><code><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Dive Into HTML5</title>
</head>
<body>
...
<mark><script src="gears_init.js"></script>
<script src="geo.js"></script></mark>
</body>
</html>
</code></pre>
<p class="legend right" style="margin-top:11.2em">
<span class="arrow"> ⇜</span> Não deixe isso no seu <head>
</p>
<p class="clear">
Agora você está pronto para usar qualquer <abbr>API</abbr> de
geolocalização.
</p>
<pre><code>if (geo_position_js.init()) {
geo_position_js.getCurrentPosition(geo_success, geo_error);
}
</code></pre>
<p>
Vamos começar devagar. Primeiro, você precisa chamar o método
<code>init()</code>. O método <code>init()</code> retorna
<code>true</code> se o suporte para a <abbr>API</abbr> de geolocalização
estiver disponível.
</p>
<pre><code>if (<mark>geo_position_js.init()</mark>) {</code></pre>
<p>
Chamando o método <code>init()</code> ele não irá buscar sua localização.
Ele somente verifica que é possível procurar sua localização. Para
encontrar sua localização, você precisa chamar o método
<code>getCurrentPosition()</code>.
</p>
<pre><code> <mark>geo_position_js.getCurrentPosition</mark>(geo_success, geo_error);</code></pre>
<p>
O método <code>getCurrentPosition()</code> irá fazer seu navegador pedir
sua permissão para encontrar e compartilhar sua localização. Se sua
geolocalização está sendo fornecida pelo Gears, irá aparecer uma janela
perguntando se você permite o Gears utilizar alguns dados. Se seu
navegador tem suporte nativo para geolocalização, a janela que irá
aparecer, é diferente. Por exemplo, o Firefox 3.5 tem suporte nativo para
geolocalização. Se você tentar procurar sua localização no Firefox 3.5,
aparecerá uma barra de notificação no topo da página perguntando se você
quer compartilhar sua localização com este site.
</p>
<p>
O método <code>getCurrentPosition()</code> passa dois parâmetros, ambos
funções. Se o método <code>getCurrentPosition()</code> conseguiu encontrar
sua localização — isto é, se você deu permissão, a <abbr>API</abbr> de
geolocalização irá funcionar como mágica — a função passada no primeiro
parâmetro será chamada. Neste exemplo, a função de callback de sucesso é
chamada de <code>geo_success</code>.
</p>
<pre><code> geo_position_js.getCurrentPosition(<mark>geo_success</mark>, geo_error);</code></pre>
<p>
A função de callback tem um único parâmetro, e que contém a posição do
usuário.
</p>
<p class="legend top" style="padding-left:6em">
<span class="arrow">↶</span> Chamada de sucesso
</p>
<pre><code>function geo_success(p) {
alert("Encontrado na latitude " + p.coords.latitude +
", longitude " + p.coords.longitude);
}</code></pre>
<p>
Se o método <code>getCurrentPosition()</code> não encontrar sua
localização — porque você não deu permissão, ou a <abbr>API</abbr> de
geolocalização falhou por algum motivo — será chamada a função no segundo
parâmetro. Neste exemplo, o callback de falha é chamado de
<code>geo_error</code>.
</p>
<pre><code> geo_position_js.getCurrentPosition(geo_success, <mark>geo_error</mark>);</code></pre>
<p>O callback de falha não tem parâmetros</p>
<p class="legend top" style="padding-left:6em">
<span class="arrow">↶</span> Chamada de erro
</p>
<pre><code>function geo_error() {
alert("Não conseguimos encontrar você!");
}</code></pre>
<p>
<code>geo.js</code> não tem suporte para o método
<code>watchPosition()</code>. Se você precisar da localização contínua,
irá precisar ativar o método <code>getCurrentPosition()</code> você mesmo.
</p>
<p class="a">❧</p>
<h2 id="putting-it-all-together">Um exemplo completo e real</h2>
<p>
Aqui está um exemplo real usando a
<a href="#geo-js"><code>geo.js</code></a> para tentar pegar sua
localização e mostrar um mapa de onde você está quase que
instantaneamente:
</p>
<p style="margin:0 auto;width:194px" id="geo-wrapper">
<img
src="i/openclipart.org_johnny_automatic_globe_man.png"
alt="homem com um globo na cabeça"
width="194"
height="317"
/><br /><span id="live-geolocation"
>Seu navegador suporta geolocation.
<a href="#" onclick="lookup_location();return false"
>Clicar para ver sua localização</a
>.</span
>
</p>
<p>
Como isso funciona? Vamos dar uma olhada. No carregamento da página, esta
página chama <code>geo_position_js.init()</code> para determinar se a
geolocalização está disponível em qualquer uma das interfaces que
<code>geo.js</code> suporta. Se tiver suporte, ele cria um link que você
pode clicar para ver sua localização. Clicando no link é chamado então o
método <code>lookup_location()</code>, aqui está:
</p>
<pre><code>function lookup_location() {
geo_position_js.getCurrentPosition(show_map, show_map_error);
}</code></pre>
<p>
Se você permitir rastrear sua localização, <em>e</em> o serviço de backend
conseguir determinar sua localização, <code>geo.js</code> chama a primeira
função de callback, <code>show_map()</code>, com um único parâmetro,
<code>loc</code>. O objeto <code>loc</code> tem uma propriedade
<code>coords</code> no qual contém sua latitude, longitude e precisão.
(Este exemplo não usa a precisão.) O resto do método
<code>show_map()</code> usa a <abbr>API</abbr> de mapas do Google Maps
para mostrar um mapa.
</p>
<pre><code>function show_map(loc) {
$("#geo-wrapper").css({'width':'320px','height':'350px'});
var map = new GMap2(document.getElementById("geo-wrapper"));
var center = new GLatLng(<mark>loc.coords.latitude</mark>, <mark>loc.coords.longitude</mark>);
map.setCenter(center, 14);
map.addControl(new GSmallMapControl());
map.addControl(new GMapTypeControl());
map.addOverlay(new GMarker(center, {draggable: false, title: "Você está aqui (mais ou menos)"}));
}</code></pre>
<p>
Se <code>geo.js</code> não conseguir determinar sua localização, ele
chamará o segundo callback, <code>show_map_error()</code>.
</p>
<pre><code>function show_map_error() {
$("#live-geolocation").html('Não foi possível determinar sua localização.');
}</code></pre>
<p class="a">❧</p>
<h2 id="further-reading">Leitura Adicional</h2>
<ul>
<li>
<a href="http://www.w3.org/TR/geolocation-API/"
><abbr>W3C</abbr> geolocation <abbr>API</abbr></a
>
</li>
<li><a href="http://tools.google.com/gears/">Gears</a></li>
<li>
<a
href="http://www.tonybunce.com/2008/05/08/Blackberry-Browser-Amp-GPS.aspx"
>BlackBerry geolocation <abbr>API</abbr></a
>
</li>
<li>
<a
href="http://www.forum.nokia.com/infocenter/index.jsp?topic=/Web_Developers_Library/GUID-4DDE31C7-EC0D-4EEC-BC3A-A0B0351154F8.html"
>Nokia geolocation <abbr>API</abbr></a
>
</li>
<li>
<a
href="http://developer.palm.com/index.php?option=com_content&view=article&id=1673#GPS-getCurrentPosition"
>Palm geolocation <abbr>API</abbr></a
>
</li>
<li>
<a href="http://bondi.omtp.org/1.0/apis/geolocation.html"
><abbr title="Open Mobile Terminal Platform">OMTP</abbr> BONDI
geolocation <abbr>API</abbr></a
>
</li>
<li>
<a href="http://code.google.com/p/geo-location-javascript/">geo.js</a>,
the geolocation <abbr>API</abbr> wrapper script
</li>
<li>
<a
href="http://msdn.microsoft.com/en-us/ie/ff468705.aspx#_HTML5_geolocation"
>Internet Explorer 9 Guide for Developers: Geolocation</a
>
</li>
</ul>
<p class="a">❧</p>
<p>
Isso foi “Você Está Aqui (Assim Como Todo Mundo Está)” e Outras Palavras
Bonitas; Consulte o <a href="table-of-contents.html">Sumário</a>, caso
queira continuar com a leitura.
</p>
<div class="pf">
<h4>Você sabia?</h4>
<div class="moneybags">
<blockquote>
<p>
Em associação a <span lang="en">Google Press</span>, O’Reilly está
distribuindo este livro em variados formatos, incluindo papel, ePub,
Mobi, <abbr>DRM</abbr>-free e <abbr>PDF</abbr>. A edição paga é
chamada <span lang="en">“HTML5: Up & Running”</span> e está
disponível agora. Este capítulo está incluído na versão paga.
</p>
<p>
Se você gostou deste capítulo e quer mostrar sua apreciação, basta
<a
href="http://www.amazon.com/HTML5-Up-Running-Mark-Pilgrim/dp/0596806027?ie=UTF8&tag=diveintomark-20&creativeASIN=0596806027"
>comprar o livro “<abbr>HTML5</abbr>: Up & Running” com esse
link afiliado</a
>
ou
<a href="http://oreilly.com/catalog/9780596806033"
>comprar a edição eletrônica diretamente da O’Reilly</a
>. Você vai ganhar um livro, e eu vou ganhar um trocado. Atualmente,
não aceito doações diretas.
</p>
</blockquote>
</div>
</div>
{% include copyright.html %}
{% include google-search.html %}
<script src="j/jquery.js"></script>
<script src="j/modernizr.js"></script>
<script src="j/gears_init.js"></script>
<script src="j/geo.js"></script>
<script src="j/dih5.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?sensor=true"></script>
<script>
function supports(bool, suffix) {
var s = 'Seu navegador ';
if (bool) {
s += 'suporta ' + suffix + '.';
} else {
s += 'não tem suporte ' + suffix + '. :(';
}
return s;
}
function lookup_location() {
geo_position_js.getCurrentPosition(show_map, show_map_error);
}
function show_map(loc) {
$('#geo-wrapper').css({width: '320px', height: '350px'});
var map = new google.maps.Map(document.getElementById('geo-wrapper'), {
zoom: 14,
mapTypeControl: true,
zoomControl: true,
mapTypeId: google.maps.MapTypeId.ROADMAP,
});
var center = new google.maps.LatLng(
loc.coords.latitude,
loc.coords.longitude,
);
map.setCenter(center);
var marker = new google.maps.Marker({
map: map,
position: center,
draggable: false,
title: 'Você está aqui (mais ou menos)',
});
}
function show_map_error() {
$('#live-geolocation').html(
'Não foi possível determinar sua localização.',
);
}
$(function() {
if (geo_position_js.init()) {
$('#live-geolocation').html(
supports(true, 'geolocation') +
' <a href="#" onclick="lookup_location();return false">Clicar para ver sua localização</a>.',
);
} else {
$('#live-geolocation').html(supports(false, 'geolocation'));
}
});
</script>
{% include google-analytics.html %}
</body>
</html>