Amélioration carte, séparation Web/Android + géolocalisation

This commit is contained in:
Emmy D'Anello 2024-12-02 20:11:31 +01:00
parent 49fcb6edbc
commit 82b73ddadf
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
8 changed files with 181 additions and 49 deletions

View File

@ -1,7 +1,7 @@
{ {
"expo": { "expo": {
"name": "traintrape-moi-client", "name": "Traintrape-moi",
"slug": "traintrape-moi-client", "slug": "traintrape-moi",
"version": "1.0.0", "version": "1.0.0",
"orientation": "portrait", "orientation": "portrait",
"icon": "./assets/images/icon.png", "icon": "./assets/images/icon.png",
@ -33,6 +33,17 @@
"resizeMode": "contain", "resizeMode": "contain",
"backgroundColor": "#ffffff" "backgroundColor": "#ffffff"
} }
],
[
"@maplibre/maplibre-react-native"
],
[
"expo-location",
{
"isAndroidBackgroundLocationEnabled": true,
"isIosBackgroundLocationEnabled": true,
"locationAlwaysAndWhenInUsePermission": "Allow $(PRODUCT_NAME) to use your location."
}
] ]
], ],
"experiments": { "experiments": {

View File

@ -1,46 +0,0 @@
import { Platform, StyleSheet } from 'react-native'
import { ThemedView } from '@/components/ThemedView'
export default function MapScreen() {
if (Platform.OS === "web") {
const maplibre = require('react-map-gl/maplibre')
const Map = maplibre.Map
return <ThemedView style={styles.page}>
<Map
initialViewState={{
longitude: 0,
latitude: 0,
zoom: 1
}}
mapStyle="https://demotiles.maplibre.org/style.json"
/>
</ThemedView>
}
else {
const MapLibreGL = require('@maplibre/maplibre-react-native')
MapLibreGL.setAccessToken(null)
return (
<ThemedView style={styles.page}>
<MapLibreGL.MapView
style={styles.map}
logoEnabled={false}
styleURL="https://demotiles.maplibre.org/style.json"
children={[]}
/>
</ThemedView>
)
}
}
const styles = StyleSheet.create({
page: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
map: {
flex: 1,
alignSelf: 'stretch',
},
});

View File

@ -0,0 +1,45 @@
import { StyleSheet } from 'react-native'
import { ThemedView } from '@/components/ThemedView'
import { useEffect, useState } from 'react'
import "maplibre-gl/dist/maplibre-gl.css"
import * as Location from 'expo-location'
import Map from '@/components/map'
import { ThemedText } from '@/components/ThemedText'
export default function MapScreen() {
const [location, setLocation] = useState<Location.LocationObject | null>(null)
const [locationAccessGranted, setLocationAccessGranted] = useState(false)
useEffect(() => {
async function watchPosition() {
let { status } = await Location.requestForegroundPermissionsAsync()
if (status !== 'granted') {
setLocationAccessGranted(false)
alert("Vous devez activer votre géolocalisation pour utiliser l'application.")
return
}
setLocationAccessGranted(true)
await Location.watchPositionAsync({accuracy: Location.Accuracy.BestForNavigation}, location => setLocation(location))
}
watchPosition()
}, [])
return (
<ThemedView style={styles.page}>
{locationAccessGranted ? <Map location={location} /> : <ThemedText>La géolocalisation est requise pour utiliser la carte.</ThemedText>}
</ThemedView>
)
}
const styles = StyleSheet.create({
page: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
map: {
flex: 1,
alignSelf: 'stretch',
},
});

38
client/components/map.tsx Normal file
View File

@ -0,0 +1,38 @@
import { StyleSheet, Text } from 'react-native'
import MapLibreGL, { Camera, FillLayer, LineLayer, MapView, PointAnnotation, RasterLayer, RasterSource, ShapeSource, UserLocation } from '@maplibre/maplibre-react-native'
import { LocationObject } from 'expo-location'
import { FontAwesome5 } from '@expo/vector-icons'
import { circle } from '@turf/circle'
export default function Map({ location }: { location: LocationObject | null }) {
MapLibreGL.setAccessToken(null)
const accuracyCircle = circle([location?.coords.longitude ?? 0, location?.coords.latitude ?? 0], location?.coords.accuracy ?? 0, {steps: 64, units: 'meters'})
return (
<MapView
logoEnabled={true}
style={styles.map}
styleURL="https://openmaptiles.geo.data.gouv.fr/styles/osm-bright/style.json">
{/* FIXME Il faudra pouvoir avoir un bouton de suivi pour activer le suivi de la caméro */}
{location && <Camera
defaultSettings={{centerCoordinate: [location?.coords.longitude, location?.coords.latitude], zoomLevel: 15}} />}
<RasterSource id="railwaymap-source" tileUrlTemplates={["https://a.tiles.openrailwaymap.org/standard/{z}/{x}/{y}.png"]}></RasterSource>
<RasterLayer id="railwaymap-layer" sourceID="railwaymap-source" style={{rasterOpacity: 0.7}} />
{/* FIXME Il faudra avoir uniquement les positions des autres personnes, puisque sa propre position peut être obtenue nativement */}
<ShapeSource id="accuracy-radius" shape={accuracyCircle} />
<FillLayer id="accuracy-radius-fill" sourceID="accuracy-radius" style={{fillOpacity: 0.4, fillColor: 'lightblue'}} aboveLayerID="railwaymap-layer" />
<LineLayer id="accuracy-radius-border" sourceID="accuracy-radius" style={{lineOpacity: 0.4, lineColor: 'blue'}} aboveLayerID="accuracy-radius-fill" />
<PointAnnotation id="current-location" coordinate={[location?.coords.longitude ?? 0, location?.coords.latitude ?? 0]}>
<FontAwesome5 name="map-marker-alt" size={24} color="blue" />
</PointAnnotation>
{/* <UserLocation animated={true} renderMode="native" androidRenderMode="compass" showsUserHeadingIndicator={true} /> */}
</MapView>
)
}
const styles = StyleSheet.create({
map: {
flex: 1,
alignSelf: 'stretch',
}
})

View File

@ -0,0 +1,26 @@
import { circle } from "@turf/circle"
import { LocationObject } from "expo-location"
import { RLayer, RMap, RMarker, RNavigationControl, RSource } from "maplibre-react-components"
export default function Map({ location }: { location: LocationObject }) {
if (!location)
// FIXME On devrait avoir la position qui se centre sur la position une fois qu'elle est établie
return <></>
const accuracyCircle = circle([location?.coords.longitude ?? 0, location?.coords.latitude ?? 0], location?.coords.accuracy ?? 0, {steps: 64, units: 'meters'})
return (
<RMap
initialCenter={[location?.coords.longitude, location?.coords.latitude]}
initialZoom={15}
mapStyle="https://openmaptiles.geo.data.gouv.fr/styles/osm-bright/style.json">
<RNavigationControl position="bottom-right" showCompass={true} showZoom={true} visualizePitch={true} />
<RSource id="railwaymap-source" type="raster" tiles={["https://a.tiles.openrailwaymap.org/standard/{z}/{x}/{y}.png"]} />
<RLayer id="railwaymap-layer" type="raster" source="railwaymap-source" paint={{"raster-opacity": 0.7}} />
<RSource id="accuracy-radius" type="geojson" data={accuracyCircle} />
<RLayer id="accuracy-radius-fill" type="fill" source="accuracy-radius" paint={{"fill-color": "lightblue", "fill-opacity": 0.4}} />
<RLayer id="accuracy-radius-border" type="line" source="accuracy-radius" paint={{"line-color": "blue", "line-opacity": 0.4}} />
{location && <RMarker longitude={location?.coords.longitude} latitude={location?.coords.latitude} />}
</RMap>
)
}

View File

@ -12,6 +12,7 @@
"@maplibre/maplibre-react-native": "^10.0.0-alpha.28", "@maplibre/maplibre-react-native": "^10.0.0-alpha.28",
"@react-navigation/bottom-tabs": "^7.0.0", "@react-navigation/bottom-tabs": "^7.0.0",
"@react-navigation/native": "^7.0.0", "@react-navigation/native": "^7.0.0",
"@turf/circle": "^7.1.0",
"expo": "~52.0.11", "expo": "~52.0.11",
"expo-blur": "~14.0.1", "expo-blur": "~14.0.1",
"expo-constants": "~17.0.3", "expo-constants": "~17.0.3",
@ -19,6 +20,7 @@
"expo-font": "~13.0.1", "expo-font": "~13.0.1",
"expo-haptics": "~14.0.0", "expo-haptics": "~14.0.0",
"expo-linking": "~7.0.3", "expo-linking": "~7.0.3",
"expo-location": "^18.0.2",
"expo-router": "~4.0.9", "expo-router": "~4.0.9",
"expo-splash-screen": "~0.29.13", "expo-splash-screen": "~0.29.13",
"expo-status-bar": "~2.0.0", "expo-status-bar": "~2.0.0",
@ -26,6 +28,7 @@
"expo-system-ui": "~4.0.4", "expo-system-ui": "~4.0.4",
"expo-web-browser": "~14.0.1", "expo-web-browser": "~14.0.1",
"maplibre-gl": "^4.7.1", "maplibre-gl": "^4.7.1",
"maplibre-react-components": "^0.1.9",
"react": "18.3.1", "react": "18.3.1",
"react-dom": "18.3.1", "react-dom": "18.3.1",
"react-map-gl": "^7.1.7", "react-map-gl": "^7.1.7",
@ -4422,6 +4425,21 @@
"url": "https://opencollective.com/turf" "url": "https://opencollective.com/turf"
} }
}, },
"node_modules/@turf/circle": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/@turf/circle/-/circle-7.1.0.tgz",
"integrity": "sha512-6qhF1drjwH0Dg3ZB9om1JkWTJfAqBcbtIrAj5UPlrAeHP87hGoCO2ZEsFEAL9Q18vntpivT89Uho/nqQUjJhYw==",
"license": "MIT",
"dependencies": {
"@turf/destination": "^7.1.0",
"@turf/helpers": "^7.1.0",
"@types/geojson": "^7946.0.10",
"tslib": "^2.6.2"
},
"funding": {
"url": "https://opencollective.com/turf"
}
},
"node_modules/@turf/destination": { "node_modules/@turf/destination": {
"version": "7.1.0", "version": "7.1.0",
"resolved": "https://registry.npmjs.org/@turf/destination/-/destination-7.1.0.tgz", "resolved": "https://registry.npmjs.org/@turf/destination/-/destination-7.1.0.tgz",
@ -6281,6 +6299,15 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/clsx": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/co": { "node_modules/co": {
"version": "4.6.0", "version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@ -7618,6 +7645,15 @@
"react-native": "*" "react-native": "*"
} }
}, },
"node_modules/expo-location": {
"version": "18.0.2",
"resolved": "https://registry.npmjs.org/expo-location/-/expo-location-18.0.2.tgz",
"integrity": "sha512-45wPrQCv5UQM/RZcOJIei8za0lSyEm5wlb3izLa9P45bqlu3ChRZhYfZz+gMQhVb/oorVqzIVUQhKRTTz7GOXQ==",
"license": "MIT",
"peerDependencies": {
"expo": "*"
}
},
"node_modules/expo-manifests": { "node_modules/expo-manifests": {
"version": "0.15.4", "version": "0.15.4",
"resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-0.15.4.tgz", "resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-0.15.4.tgz",
@ -10960,6 +10996,25 @@
"url": "https://github.com/maplibre/maplibre-gl-js?sponsor=1" "url": "https://github.com/maplibre/maplibre-gl-js?sponsor=1"
} }
}, },
"node_modules/maplibre-react-components": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/maplibre-react-components/-/maplibre-react-components-0.1.9.tgz",
"integrity": "sha512-UjKZBi/qdKKQ1UejWoSVMedaU3T8D/FHxIj/WSjKbxrqhe1wWk4Mo79xT9yM6N/l1HXyPlf0RXeHbwLv5edh3g==",
"license": "MIT",
"dependencies": {
"clsx": "^2.1.1"
},
"peerDependencies": {
"maplibre-gl": "^3.0.0 || ^4.0.0",
"react": "^17.0.0 || ^18.0.0",
"react-dom": "^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"maplibre-gl": {
"optional": false
}
}
},
"node_modules/marky": { "node_modules/marky": {
"version": "1.2.5", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz", "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz",

View File

@ -18,6 +18,7 @@
"@maplibre/maplibre-react-native": "^10.0.0-alpha.28", "@maplibre/maplibre-react-native": "^10.0.0-alpha.28",
"@react-navigation/bottom-tabs": "^7.0.0", "@react-navigation/bottom-tabs": "^7.0.0",
"@react-navigation/native": "^7.0.0", "@react-navigation/native": "^7.0.0",
"@turf/circle": "^7.1.0",
"expo": "~52.0.11", "expo": "~52.0.11",
"expo-blur": "~14.0.1", "expo-blur": "~14.0.1",
"expo-constants": "~17.0.3", "expo-constants": "~17.0.3",
@ -25,6 +26,7 @@
"expo-font": "~13.0.1", "expo-font": "~13.0.1",
"expo-haptics": "~14.0.0", "expo-haptics": "~14.0.0",
"expo-linking": "~7.0.3", "expo-linking": "~7.0.3",
"expo-location": "^18.0.2",
"expo-router": "~4.0.9", "expo-router": "~4.0.9",
"expo-splash-screen": "~0.29.13", "expo-splash-screen": "~0.29.13",
"expo-status-bar": "~2.0.0", "expo-status-bar": "~2.0.0",
@ -32,6 +34,7 @@
"expo-system-ui": "~4.0.4", "expo-system-ui": "~4.0.4",
"expo-web-browser": "~14.0.1", "expo-web-browser": "~14.0.1",
"maplibre-gl": "^4.7.1", "maplibre-gl": "^4.7.1",
"maplibre-react-components": "^0.1.9",
"react": "18.3.1", "react": "18.3.1",
"react-dom": "18.3.1", "react-dom": "18.3.1",
"react-map-gl": "^7.1.7", "react-map-gl": "^7.1.7",

View File

@ -13,6 +13,6 @@
"**/*.tsx", "**/*.tsx",
".expo/types/**/*.ts", ".expo/types/**/*.ts",
"expo-env.d.ts", "expo-env.d.ts",
"app/(tabs)/index.jsx" "app/(tabs)/index.tsx"
] ]
} }