Amélioration carte, séparation Web/Android + géolocalisation
This commit is contained in:
parent
49fcb6edbc
commit
82b73ddadf
@ -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": {
|
||||||
|
@ -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',
|
|
||||||
},
|
|
||||||
});
|
|
45
client/app/(tabs)/index.tsx
Normal file
45
client/app/(tabs)/index.tsx
Normal 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
38
client/components/map.tsx
Normal 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',
|
||||||
|
}
|
||||||
|
})
|
26
client/components/map.web.tsx
Normal file
26
client/components/map.web.tsx
Normal 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>
|
||||||
|
)
|
||||||
|
}
|
55
client/package-lock.json
generated
55
client/package-lock.json
generated
@ -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",
|
||||||
|
@ -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",
|
||||||
|
@ -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"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user