Geolocation-API¶
Hint
Aktueller Stand vor Geolocation-API:
- Frontend
- Backend
- Collection post
- Collection post.files
- Collection post.chunks
Die Geolocation-API wird von allen Browsern unterstützt (sogar Internet Explorer). Es gibt viele Dokumentationen darüber, z.B. hier, hier und hier. Die Verwendung ist recht einfach.
In der index.html
haben wir uns bereits einen Button erstellt, für den wir "nur noch" das click
-Ereignis behandeln müssen.
83 84 85 86 |
|
Zunächst vereinfachen wir uns in der feed.js
wieder den Zugriff auf den Button und den Spinner (Loader) und erstellen noch eine globale Variable fetchedLocation
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
und wir setzen den Loader
in der feed.css
auf unsichtbar:
23 24 25 |
|
create-post #pick-image
stand dort schon, wir haben nur noch den Selektor #create-post #location-loader
hinzugefügt.
Wir fügen in der feed.js
die Behandlung des click
-Ereignisses für den Location
-Button hinzu und auch noch, wie für die Kamera, eine initializeLocation()
-Funktion, in der geprüft wird, ob die Geolocation
-API überhaupt im Browser verfügbar ist:
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 |
|
In der initializeLocation()
-Funktion wird geprüft, ob der Browser die Geolocation
-API unterstützt. Wenn nicht, wird der Location
-Button versteckt. Wir haben trotzdem, sicherheitshalber, die Abfrage nochmal in die Behandlung des click
-Ereignisses für diesen Button eingefügt (Zeilen 22-24
), obwohl dies nicht wirklich notwendig ist, da der Button nicht angeklickt werden kann, wenn die Geolocation
-API nicht unterstützt wird, da er nicht angezeigt wird.
Wenn auf den Button geklickt wurde, setzen wir den Button selbst auf unsichtbar (Zeile 26
) und den Spinner (Loader) auf sichtbar (Zeile 27
). Zeile 29
zeigt den eigentlichen Zugriff auf die aktuelle Position. Dort wird die Funktion getCurrentPosition()
der Geolocation
-API aufgerufen. Wir übergeben drei Parameter:
- der erste Parameter ist die (Callback-)Funktion, die die aktuelle Position zurückgibt. Wenn diese Funktion ausgeführt wird, setzen wir den Button wieder auf sichtbar (Zeile
30
) und den Loader auf unsichtbar (Zeile31
). Die aktuelle Positionposition
enthält die Eigenschaftcoords
, die dielatitude
undlongitude
als Werte enthält (siehe GeolocationPosition und GeolocationCoordinates). Diese Position geben wir auf der Konsole aus (Zeile33
). Wir befüllen daslocationInput
-Eingabefeld noch mit einem Dummy-Wert und fokussieren auf das Eingabefeld (Zeilen34-35
). - der zweite Parameter ist eine Funktion, die ausgeführt wird, wenn ein Fehler auftritt. Mögliche Fehler sind, dass im Browser der Zugriff auf die Position deaktiviert wurde, dass die Nutzerin den Zugriff auf die aktuelle Position blockiert hat oder dass die Position nicht "schnell genug" ermittelt werden konnte. Im Fehlerfall geben wir den Fehler auf der Konsole aus und schalten den Button wieder ein und den Loader wieder aus (Zeilen
37-39
). - der dritte Parameter ist ein JavaScript-Objekt mit
options
. Wir wählen hier nur eine einzige Option, nämlich wie lange nach der aktuellen Position gesucht werden soll. In der Einstellung erfolgt dertimeout
nach5 sek
.
Wir passen nun in der feed.js
noch die beiden Funktionen openCreatePostModal()
und closeCreatePostModal()
an:
80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
|
Wenn Sie die Anwendung nun starten, werden Sie gefragt, ob Sie die Abfrage nach Ihrem Standort zulassen oder blockieren wollen. Die meisten von Ihnen werden aber die Ortungsdienste ausgeschaltet haben. Dann ist auch die Abfrage zunächst egal. Im Mac kann man diese (kurzzeitig, dann wieder ausschalten) über Systemeinstellungen --> Sicherheit & Datenschutz --> Reiter Datenschutz --> Ortungsdienste
für Google Chrome
aktivieren.
Wenn Sie die Positionsbestimmung zulassen, dann wird nach dem Klicken auf den Location
-Button die aktuelle Position auf der Konsole eingegeben und im Formular erscheint unter Ort In Berlin
.
Wir machen nichts weiter mit der aktuellen Position. Es gibt viele Möglichkeiten, die jetzt noch ausprobiert werden könnten. Dazu gehören beisielsweise:
- Wir könnten mithilfe der Google-Geolocation-API die Adresse ermitteln, die Google für eine gegebene Position (
longitude
undlatitude
) zurückgibt. Dazu bräuchten wir aber auch einen API-Key von Google. - Wir könnten das Gleiche mit der Nominatim-API für Open Street Map machen. Sie können den Service hier einmal ausprobieren, indem Sie Ihre
latitude
undlongitude
aus der Konsolenausgabe eingeben. - Wir könnten OpenLayers verwenden, um die Position auf einer Karte anzuzeigen.
- Wir könnten die Datenbank erweitern und für alle Posts auch noch die Koordinaten der Position abspeichern und dann alle Posts auf einer Karte (mithilfe von OpenLayers + OpenStreetMap) visualisieren.
Beispiel nominatim.org¶
Die oben genannten Verwendungsbeispiele sind alle relativ einfach, da die jeweiligen APIs wirklich gut sind. Wir zeigen hier exemplarisch die Verwendung der Nominatim-API, mit deren Hilfe wir für gegebene Breiten- und Längengrade ein Adress-Objekt zurückbekommen. Genauer gesagt, handelt es sich um ein Open Street Map (OSM)-Objekt. Einen groben Überblick über die Endpunkte der Nominatim-API erhalten Sie hier. Uns interessiert dabei insbesondere der /reverse-Endpunkt, der ein OSM-Objekt für eine gegebene Lokation zurückgibt.
Prinzipiell sieht die Anfrage wie folgt aus:
https://nominatim.openstreetmap.org/reverse?format=<value>&lat=<value>&lon=<value>&<params>
- Als Rückgabe-
format
kann einer der folgenden Werte verwendet werden:[xml|json|jsonv2|geojson|geocodejson]
. Der Standard istxml
. Wir sollten am bestenjsonv2
verwenden. - Für
lat
undlong
setzen wir dielatitude
undlongitude
ein, die wir infetchedLocation
speichern. - Für mögliche weitere Parameter
<params>
, wie z.B.zoom
,extratags
odernamedetails
, schauen Sie hier.
Wenn wir z.B. folgende Anfrage stellen:
GET https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=52.457310&lon=13.526877
erhalten wir als Response folgendes JSON:
{
"place_id": 106322469,
"licence": "Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright",
"osm_type": "way",
"osm_id": 25346348,
"lat": "52.45699635",
"lon": "13.526577702867113",
"place_rank": 30,
"category": "building",
"type": "university",
"importance": 0,
"addresstype": "building",
"name": "Gebäude C",
"display_name": "Gebäude C, Johannes-Kraaz-Straße, Oberschöneweide, Treptow-Köpenick, Berlin, 12459, Deutschland",
"address": {
"building": "Gebäude C",
"road": "Johannes-Kraaz-Straße",
"suburb": "Oberschöneweide",
"borough": "Treptow-Köpenick",
"city": "Berlin",
"state": "Berlin",
"postcode": "12459",
"country": "Deutschland",
"country_code": "de"
},
"boundingbox": [
"52.4561412",
"52.4577257",
"13.5255179",
"13.5274139"
]
}
Wir könnten nun einen ausgewählten Wert in unser Formular übernehmen, z.B. display_name
oder suburb
oder city
. Wir zeigen im Folgenden die Übernahme von display_name
in das Eingabeformular:
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 |
|
- In den Zeilen
35-38
setzen wir die URL zusammen, unter der wirnominatim.org
anfragen. In Zeile40
erfolgt die Anfrage mithilfe derfetch
-API. Wir erhalten einResponse
-Objekt zurück, das wir mithilfe vonres.json()
so extrahieren, dass es dem oben gezeigten JSON entspricht.
Beispiel OpenLayers.org¶
OpenLayers stellt eine Bibliothek von JavaScript- und CSS-Funktionalitäten bereit, um Landkarten in die Webanwendung einzubinden. Wir zeigen die Anwendung hier an einer sehr einfachen Einführung, die im Prinzip dem Einführungsbeispiel von OpenLayers entspricht.
Einbinden in die index.html¶
Zunächst kann die CSS- und JavaScript-Bibliothek über ein CDN eingebunden werden:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Dann integrieren wir ein <div>
-Element, in dem später die Landkarte erscheint:
84 85 86 87 88 89 90 91 92 93 94 95 96 |
|
Anpassen der feed.css¶
Zunächst müssen wir in der feed.js
einen Selektor ändern. Wir haben die map
innerhalb des div
mit der id="create-post"
angelegt. In der feed.js
befindet sich folgender Eintrag:
16 17 18 19 20 21 |
|
Wir sprechen also alle HTML-Elemente video
und canvas
an, die sich im div
mit der id="create-post"
befinden. Allerdings wird unsere map
auch ein canvas
-Element enthalten, welches ebenfalls mit angesprochen (und auf display: none
gesetzt) werden würde. Wir spezialisieren diese Selektoren nun, indem wir jeweils die id
s des video
- und des canvas
-Elementes verwenden, die sich um die Aufnahme des Fotos kümmern:
16 17 18 19 20 21 |
|
Nun können wir die Eigenschaften hinzufügen, die für die map
relevant sind:
62 63 64 65 66 67 |
|
Sie können für Höhe und Breite auch relative oder auch andere absolute Werte setzen. Zunächst ist das div
mit der CSS-Klasse map
aber auf nicht sichtbar gesetzt.
Anpassen der feed.js¶
In der feed.js
erweitern wir die fetch()
-Anfrage an nominatim.org
. Diese sieht bis jetzt so aus:
40 41 42 43 44 45 46 47 48 49 50 51 52 |
|
Siehe die feed.js
aus Beispiel nominatim.org oben.
Unter Verwendung der Variablen fetchedLocation
, die die longitude
und latitude
unseres Standortes enthält, fügen wir nun die Erstellung einer Map mithilfe von OpenLayers hinzu:
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 |
|
- In Zeile
53
wird dasdiv
, das diemap
enthält, auf sichtbar gesetzt (Definieren Sie dazulet mapDiv = document.querySelector('#map');
). DerlocationButton
und der Spinner werden unsichtbar. - Mit
new ol.Map()
wird eine neue Map erstellt (Zeile55
). - Dieses
Map
-Objekt wird mittarget: 'map'
demdiv
mit derid="map"
zugewiesen (Zeile56
). - Das
layers
-Array enthält alle Schichten, die zur Map hinzugefügt werden (Zeile57
). - In unserem Fall wird eine Schicht hinzugefügt, nämlich eine Kachel (Tile)-Schicht, die die Landkarte enthält. Diese wird in unserem Fall von der Quelle OSM (also Open Street Map) geholt. Beachten Sie Ihre Konsole. Sie werden Einträge in der folgenden Art darin finden:
Das sind die Bilder, aus denen die Landkarte zusammengesetzt wird.
- Die eigentliche Ansicht wird mit
view
definiert. Wir erstellen ein einfachesView
-Objekt, das durch dencenter
-Punkt ([fetchedLocation.longitude, fetchedLocation.latitude]
) und einzoom
-Level beschrieben wird (hierzoom:12
). Je höher daszoom
-Level, je höher wird hineingezoomt. Zoom-Level0
zeigt die Welt. (Zeilen62-65
)
Die Zeilen 55-65
genügen bereits, um die Karte anzuzeigen. Wir haben aber hier auch noch einen Marker für den aktuellen Standort hinzugefügt. Dazu wird eine weitere Layer
definiert und der Map mithilfe von map.addLayer()
hinzugefügt. Dies geschieht hier in den Zeilen 68-78
. Bei dem Marker handelt es sich hier um einen Point
, der wiederum auf [fetchedLocation.longitude, fetchedLocation.latitude]
gesetzt wird. Beachten Sie, dass die Reihenfolge sowohl in der View
als auch beim Feature
zunächst longitude
und dann latitude
ist!
Success
Wir haben erfolgreich den Zugriff auf die Kamera (MediaDevices-API) und die Geolocation-API ausprobiert und in unsere Anwendung eingebunden. Die MediaDevices-API bietet neben der video
-Eigenschaft auch noch die audio
-Eigenschaft, um das Mikrofon zu verwenden. Neben der Geolocation-API haben wir auch zwei weitere Services bzw. Bibliotheken verwendet, nämlich nomination.org und OpenLayers. Der Umgang mit den Karten kann beliebig erweitert werden. Beispielsweise könnten auch alle Blogs auf einer Landkarte angezeigt werden, je nachdem, wo sie erstellt wurden. Sie könnten anklickbar sein und dann detailliert angezeigt werden. Das ist alles relativ leicht möglich. Ihrer Phantasie und Ihren Möglichkeiten sind hier keine Grenzen gesetzt. Wir könnten hier auch noch auf die Sensoren der Mobilgeräte eingehen (z.B. Beschleunigungssensor). Das machen wir aber in diesem Semester nicht.