Vi gir dere en enkel fremgangsmåte på å sette opp en React-applikasjon med et Maplibre-kart. Deretter skal dere utvide kartfunksjonaliteten til applikasjonen ved å bruke data fra Norkart. Her kan dere velge mellom forskjellige oppgaver, eller lage noe helt selv!
Still spørsmål dersom dere står fast eller noe er uklart! 😄
Lykke til!
- React-dokumentasjon: https://react.dev/reference/react
- TypeScript-dokumentasjon: https://www.typescriptlang.org/docs/
- Material UI (MUI) dokumentasjon: https://mui.com/material-ui/getting-started/
- MapLibre-dokumentasjon: https://maplibre-react-components.pentatrion.com/getting-started
Før dere starter må dere ha noe programvare installert (installer kun det dere ikke har fra før):
- Git. Følg instruksjonene som gjelder for ditt OS her: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git. Sjekk at git er installert ved å kjøre følgende i en terminal:
git --version
-
Github. Lag deg en bruker her https://github.com/
-
Node.js med npm https://nodejs.org/en/download
Sjekk at du har fått installert node med npm!
node --version
npm --version
- En code editor (vs code anbefales). https://code.visualstudio.com/download
-
For å få din egen versjon av prosjektet under egen GitHub-bruker fork-er du dette prosjektet. Dette gjøres ved å trykke
fork
oppe i høyre hjørnet. Behold default innstillinger. -
I en terminal: Finn fram til fillokasjonen hvor dere vil lagre prosjektet og klon repoet (deres egen versjon av prosjektet som dere nettopp forket):
git clone https://github.com/<YOUR_GITHUB_USERNAME>/norkart-webkurs-React.git
-
Åpne VSCode og åpne prosjektet du nettopp clonet.
-
Åpne ny terminal. Installer npm pakkene til prosjektet. De relevante pakkene kan sees i
package.json
filen i prosjektet. Vi bruker for eksempelmaplibre-gl
biblioteket til å vise kart på nettsiden.
npm install
- API-nøkkel. I rotmappa av repoet, lag en fil ved navn ".env" og legg inn følgende:
VITE_API_KEY=
Bak "=" skal dere legge inn API-nøkkelen dere får tildelt.
API-nøkkelen skal IKKE legges noe annet sted enn her, og .env skal IKKE lastes opp på GitHub!!
- Kjør opp prosjektet lokalt:
npm run dev
Dette bør åpne nettleseren din på http://localhost:5173/.
HURRA! Du kan nå kalle deg for en React-utvikler!
Nå som du har en enkel kart-applikasjon kan du begynne å utvide den med mer spennende funksjonalitet!
Under finner du forskjellige oppgaver som kan gjøres i hvilken som helst rekkefølge (med unntak av noen ekstraoppgaver), med litt ulik grad av veildening. Dersom du føler deg komfortabel nok med React og TypeScript kan du også gjøre noe helt annet med de dataene og verktøyene som er tilgjengelig!
Gjerne ta utgangspunkt i Maplibre sin tutorial for å legge til flere funksjoner i appen. ℹ️ Husk at vi bruker TypeScript og ikke JavaScript, så du må kanskje gjøre noen små endringer på koden i tutorialen for at det skal funke. Spør gjerne om hjelp!
Funksjonen getHoydeFromPunkt.ts kan benyttes til å hente høyde for et geografisk punkt, som vist i kart-komponenten MapLibreMap.tsx, hvor høyden for et punkt lagres i staten "pointHoyde" og vises konsollen i nettleseren når man klikker i kartet. Din oppgave er å implementere en visning av denne høyden i applikasjonen.
Her kan du for eksempel benytte deg av MapLibre-komponenten RPopup, eller lage en egen komponent ved siden av eller under kartet som viser latitude, longitude og høyde for valgt punkt. Da kan man for eksempel bruke MUI-komponenten Card eller legge inn detaljene direkte inn i Overlay-komponenten.
Hint: Latitude og longitude av punktet man klikker på blir lagret i clickPoint
-state'en. Disse må brukes dersom du velger å prøve RPopup.
SearchBar.tsx eksporterer en komponent som kan brukes til å søke etter adresser. For å vise den i applikasjonen må den importeres og plasseres i en komponent som faktisk rendres, som MapLibreMap. I denne filen, importer SearchBar ved å plassere følgende øverst i filen:
import { SearchBar, type Address } from './SearchBar';
Videre må vi lage en state hvor en valgt adresse kan lagres og en state-setter-funksjon som kan oppdatere den. Dette oppnås ved å legge til følgende i MapLibreMap-komponenten:
export const MapLibreMap = () => {
const [hoyde, setHoydeAtPunkt] = useState<undefined | number>(undefined);
const [address, setAddress] = useState<Address | null>(null); // <--- Legg til dette!
...
}
For å rendre Searchbar-komponenten, plasser den inni Overlay-komponenten, slik:
export const MapLibreMap = () => {
...
return (
<RMap
...
>
<Overlay>
<SearchBar setAddress={setAddress}/> // <--- Legg til denne
</Overlay>
<DrawComponent />
</RMap>
);
};
Her gir vi state-setter-funksjonen videre til komponenten, slik at komponenten kan oppdatere den. Nå skal Søkefeltet vises i applikasjonen!
Som du derimot kanskje ser kommer det ikke opp noen valgalternativer når man søker. Her kan funksjonen getAddresserFromSearchText benyttes til å hente adresser fra et Norkart API som matcher en søketekst. Endre komponenten SearchBar til å bruke denne funksjonen til å hente adresser.
Hint: Adressealternativer settes i konstanten "adresser" i useEffect i komponenten. Husk å bruk "await", siden getAddresserFromSearchText er en asynkron funksjon! Du kan se på hvordan getHoydeFromPunkt blir brukt i MapLibreMap.tsx som et eksempel.
Når du har fått til dette kan du gå videre til å få kartet til å "fly til" en valgt adresse. Dette kan man gjøre ved å benytte seg av staten vi opprettet ved navn "address", som oppdateres når man velger en adresse. Det som gjenstår er å benytte seg av komponenten MapFlyTo, og å gi den lagrede adresseposisjonen til denne komponenten:
<RMap
minZoom={6}
...
>
{address && (
<MapFlyTo
lngLat={
new LngLat(address.PayLoad.Posisjon.X, address.PayLoad.Posisjon.Y)
}
/>
)}
</RMap>
Norkart har også et API-endepunkt for å hente data for et bygning ved et punkt. For å hente og bruke denne må funksjonen getBygningAtPunkt.ts implementeres. Se filen for implementasjonsinstruksjoner.
Når implementert kan funksjonen brukes i MapLibreMap-komponenten for å hente omrisset av en bygning. Gjør følgende:
- Legg til følgende importer øverst i komponent-fila under de andre importene:
import { getBygningAtPunkt } from '../api/getBygningAtPunkt';
import type { GeoJSON } from 'geojson';
- Definer en state og en state-setter for bygningsomrisset, under de andre state og state-setterne:
const [bygningsOmriss, setBygningsOmriss] = useState<GeoJSON | undefined>(undefined);
- Endre onMapClick-funksjonen til å hente bygningsdata ved klikk og til å oppdatere staten. Merk at implementasjonen nedenfor forutsetter at getBygningAtPunkt returnerer én bygning og ikke en liste av bygninger.
const onMapClick = async (e: MapLayerMouseEvent) => {
const bygningResponse = await getBygningAtPunkt(e.lngLat.lng, e.lngLat.lat)
if (bygningResponse?.FkbData?.BygningsOmriss) {
const geoJsonObject = JSON.parse(bygningResponse.FkbData.BygningsOmriss);
setBygningsOmriss(geoJsonObject);
} else {
setBygningsOmriss(undefined);
}
...
}
- Legg til en polygon-stil. Denne kan du redigere etter eget ønske:
const polygonStyle = {
"fill-outline-color": "rgba(0,0,0,0.1)",
"fill-color": "rgba(18, 94, 45, 0.41)"
}
- Oppdater MapLibre importer i MapLibreMap-komponenten:
import { RLayer, RMap, RSource, useMap } from 'maplibre-react-components';
- Legg til komponenter for å vise et polygon for valgt bygning. Disse rendres kun når bygningsOmriss er definert.
<RMap
...
>
{bygningsOmriss &&
<>
<RSource id="bygning" type="geojson" data={bygningsOmriss} />
<RLayer
source="bygning"
id="bygning-fill"
type="fill"
paint={polygonStyle}
/>
</>
}
</RMap>
API-et returnerer også andre data knyttet til en bygning. Kanskje du kan vise disse dataene ved hjelp av en RPopup eller et MUI Card?
Dersom du har implementert adressesøk (se Oppgave 3), kan du bruke posisjonen i Adresse-objektet til å hente en bygning på adressen og vise dette i kartet!
Norkart har også et API-endepunkt for Risiko- og sårbarhetsdata (ROS-data) for bygninger. Implementer funksjonen getRosDataForBygning og hent data for en valgt bygning. Vis ROS-data enten i kart eller ved å bruke MUI-komponenter utenfor kartet.
Implementer funksjonen getTakflateDataForPunkt for å hente solmengde-data for et tak ved et punkt.
Når implementert kan du modifisere funksjonen onMapClick i MapLibreMap-komponenten for å hente solmengde-data for et tak ved et valgt punkt i kartet. Respons-objektet inneholder blant annet en geometri som kan vises i kartet (se oppgave 4 for å se hvordan dette kan gjøres).
I tillegg innholder responsen den beregnede solmengden (i kWh/m^2) som treffer taket i en gitt måned. Denne informasjonen kan for eksempel vises ved hjelp av komponenten MUI Table.
Dersom du har implementert getBygningAtPunkt (se oppgave 4), kan du benytte bygningsnummeret som returneres fra API-et til å hente solmengde-data for alle takene på en valgt bygning. For å gjøre dette må du implementere getTakflateDataForBygning. Responsen fra dette API-kallet kan brukes både til å vise alle tak i kartet og til å vise total solmengde på alle tak ved forskjellige tider av året.
Her står du fritt til å bruke andre åpne geografiske data til å utvide appen. Eksempel er:
- Sjekk ut maplibre gl sine eksempler: http://maplibre.org/maplibre-gl-js/docs/examples/
- Visualisere historiske Oslo bysykkel data: https://oslobysykkel.no/en/open-data/historical
- Lag et Koropletkart av Norgesbefolkning. En Json fil er lagt ved (se befolkning_5km.json) som viser Norges befolkning delt opp i 5x5km ruter.
- Visualiser din egen data. Du kan lage GeoJson filer her: https://geojson.io/#map=2/20.0/0.0