Mappe e coordinate

Una mappa è una vista su una collezione, come una lista o una tabella: una riga è un punto, e il corpo della direttiva è il modello del fumetto. Quello che cambia rispetto alle altre viste è come una riga dice dov’è.

Il motore della mappa è un pezzo caricato solo se il documento ne ha una.

::map … ::/map

::map{path="segnalazioni" coords="posizione" height="26rem"}
**{tipo}** — {via}
{note}
::/map
Attributo
pathLa collezione
coordsIl campo che tiene le due coordinate in una stringa, "45.46, 9.18" — il formato che ::geo scrive
lat / lonI due campi, quando le coordinate stanno in due colonne (per difetto lat e lon)
geojsonIl campo che tiene una geometria GeoJSON: ogni riga diventa un’area invece che un punto
fillCon geojson, il campo numerico che colora le aree a quantili di blu
centerIl centro iniziale, "lat, lon"
zoomLo zoom iniziale, da 0 (il mondo) a 19 (la via)
heightUn’altezza CSS; senza, 24rem
tilesUn’altra base cartografica: un URL https con i segnaposti {z}/{x}/{y}
attributionLa riga di credito che quel fornitore di tasselli richiede

Il fumetto è un modello di riga come quello di ::list: {campo} viene sostituito col valore, e il valore arriva come testo, mai come marcatura — una riga che contiene <script> mostra quei caratteri.

Una riga senza coordinate valide semplicemente non ha un punto. Non è un errore e non interrompe niente: in una collezione appena importata la metà degli indirizzi non è ancora stata risolta, ed è normale.

La vista segue i punti, finché non la muovi

Senza center, la mappa si inquadra da sé sui punti che ha. Continua a farlo mentre le righe cambiano — si aggiunge una segnalazione e la mappa si allarga — fino al primo gesto del lettore. Da quel momento la vista è sua e non gliela si sposta più sotto le mani, che è la cosa che rende insopportabili le mappe che si riposizionano da sole.

Le aree, e la coropletica

::od-query{into="sezioni" sql="SELECT * FROM istat_sezioni WHERE codice_istat = '{#comune}'"}

::map{path="sezioni" geojson="geojson" fill="popolazione"}
**{sezione}** — {popolazione} abitanti
::/map

Con geojson ogni riga è un poligono invece di un punto, e fill lo colora secondo un campo numerico: la scala è a quantili, non lineare, così una distribuzione con una coda lunga — che è come sono fatti quasi tutti i dati territoriali — non produce una mappa di un colore solo con tre eccezioni.

I tasselli

Per difetto sono quelli di OpenStreetMap, con il credito che la loro licenza richiede. Sono l’unica ragione per cui la politica di sicurezza dell’app concede img-src https:. Un tiles= diverso è accettato solo se è https e contiene {z}/{x}/{y}; altrimenti si torna a OpenStreetMap. Con un tema scuro i tasselli vengono ritinti via CSS, perché una mappa chiarissima dentro un’interfaccia scura è l’unica cosa che si vede nella stanza.

::geo — il punto di chi compila

::form{path="segnalazioni"}
::input{field="tipo" legend="Tipo di segnalazione"}
::geo{field="posizione" legend="Dove"}
::save{label="Segnala"}
::/form

È un campo di modulo con accanto un pulsante: premuto, chiede al dispositivo la sua posizione e la scrive nel campo come "lat, lon" — esattamente il formato che ::map{coords} legge. Prende field, legend e form (quando il campo sta fuori dal modulo che lo possiede), come ogni altro campo.

La posizione si chiede su un gesto, mai da sola all’apertura della pagina.

::geocode — dagli indirizzi alle coordinate

::geocode{path="fornitori" from="indirizzo" to="coords" label="Trova sulla mappa"}

Un pulsante che risolve in coordinate gli indirizzi già scritti nelle righe.

Attributo
pathLa collezione
fromIl campo che tiene l’indirizzo
toIl campo dove finiscono le coordinate; senza, coords
valueForma a indirizzo singolo: l’indirizzo, o un #key che lo tiene
urlUn endpoint Nominatim /search proprio, invece di quello pubblico
labelChe cosa dice il pulsante

Tre cose lo rendono usabile su una collezione vera:

La forma a indirizzo singolo scrive una chiave reattiva invece che una riga:

::textfield[indirizzo]{label="Indirizzo"}
::geocode[punto]{value="#indirizzo" label="Trova"}
::map{path="poi" center="#punto" zoom="16"}
::/map

Due risolutori, prima quello locale

Un indirizzo italiano viene cercato in ANNCSU, l’archivio nazionale dei numeri civici — venti milioni, con le coordinate — tenuto dal servizio open data sulla stessa origine dell’app. Quella risposta è immediata, non ha limiti di frequenza e non dice a nessuno che cosa è stato cercato. Solo se lì non si trova niente la richiesta esce verso Nominatim, con la sua politica di una richiesta al secondo.

Ricade fuori per due ragioni oneste, e vale la pena saperle entrambe: ANNCSU è solo Italia, e 2.402 comuni su 7.890 non hanno coordinate lì dentro. Un indirizzo all’estero, o in uno di quei comuni, si risolve lo stesso — ma non da qui. Dove il servizio open data non c’è, tutti gli indirizzi vanno a Nominatim come prima.

Quale dei due abbia risposto si vede nel pannello di rete e in nessun altro posto, deliberatamente: chi chiede «dov’è questo indirizzo» deve ricevere la stessa risposta in entrambi i casi.