Cały kod źródłowy oraz przykładowy projekt dostępny jest tutaj: https://github.com/AndreiMaksimovich/react-native-maps-web–demo
Android | iOS | Web |
Web demo: https://demos.amaxsoftware.com/01.react-native-maps-web/

Problem
Mapy są jedną z najczęściej spotykanych funkcji we współczesnych aplikacjach. W React Native domyślnym wyborem do obsługi map jest biblioteka react-native-maps. Choć działa dobrze na iOS i Androidzie, nie zapewnia wsparcia dla wersji web. W rzeczywistości żadna z popularnych, ugruntowanych bibliotek mapowych nie oferuje obecnie pełnego wsparcia dla kompilacji webowej.
Istnieje biblioteka teovillanueva/react-native-web-maps, jednak od dłuższego czasu nie jest aktywnie rozwijana i wciąż zapewnia jedynie bardzo ograniczoną funkcjonalność.
Cel
Naszym celem było stworzenie prostego rozszerzenia/wrapper-a dla powszechnie używanej, de facto standardowej biblioteki react-native-maps. Rozszerzenie powinno być możliwie najmniej inwazyjne, a jednocześnie zapewniać kluczowe funkcje działające bezproblemowo na Androidzie, iOS oraz Web. W szczególności powinno:
- Wyświetlać mapy w spójny sposób na Androidzie, iOS i Web
- Udostępniać API do podstawowych interakcji z mapą, takich jak zmiana położenia kamery
- Obsługiwać wyświetlanie znaczników (markers) na mapie
- Obsługiwać polilinie dla tras
- Pokazywać lokalizację użytkownika wraz z kierunkiem/headingiem urządzenia
Rozwiązanie
Mapy
Najprostszym i bezpośrednim sposobem na uzyskanie wsparcia map wieloplatformowych jest rozszerzenie istniejącej biblioteki o własny wrapper. Wrapper ten pośredniczy (proxy) w wywołaniach oryginalnej funkcjonalności na Androidzie i iOS, a jednocześnie dostarcza własne komponenty odtwarzające to samo zachowanie w wersji Web, z identycznymi lub rozszerzonymi właściwościami.
Biblioteki bazowe
- Android i iOS – używamy react-native-maps.
- Web – korzystamy z vis.gl/react-google-maps.
Struktura projektu
/src/react-native-maps-web/index.ts
– eksportuje komponenty w tym samym stylu co react-native-maps. Dzięki temu zależności mogą być łatwo ręcznie podmieniane, refaktoryzowane lub aliasowane w bundlerze webowym.- Każdy proxowany komponent (np.
Component.tsx
) ma swój odpowiednik webowy (Component.web.tsx
), który jest automatycznie używany podczas budowania wersji web. /src/react-native-web/Types.ts
– definiuje rozszerzone typy i właściwości. Opcje specyficzne dla Web są poprzedzane prefiksemweb
. Na przykładMapView
zawierawebGoogleMapsApiKey
, wymagany wyłącznie w implementacji web (podczas gdy iOS korzysta z prebuild hardcoded configuration, a Android z pliku manifest).
Kontrola mapy
Komponent MapView
udostępnia mapRef
, co pozwala na programową kontrolę mapy. Podstawowy interfejs zdefiniowany jest w Types.ts
(Map
), a implementacje specyficzne dla platform znajdują się w MapRN.ts
oraz MapWeb.ts
.
Lokalizacja użytkownika
Lokalizacja użytkownika obsługiwana jest poprzez własny provider znajdujący się w /src/foreground-location-provider/
.
- Android i iOS – oparte na bibliotece expo-location.
- Web – wykorzystuje wbudowane API navigator.geolocation.
Choć expo-location technicznie działa w przeglądarce, jednak okazało się, że działa czasami błędne i niestabilne, dlatego zdecydowaliśmy się na natywną implementację przeglądarkową.
Kierunek urządzenia (Device Heading)
Dane o kierunku urządzenia pochodzą z innego customowego providera w /src/device-heading-provider/
.
- Android i iOS – zaimplementowane przy pomocy react-native-compass-heading.
- Web – korzysta z API AbsoluteOrientationSensor.