Si eres nuevo en React Expo y deseas rastrear la distancia recorrida por un usuario, este artículo te proporcionará una guía y soluciones a algunos problemas comunes que podrías enfrentar.
Funcionalidades a Implementar
- Permiso de Localización: Solicitar permiso al usuario para acceder a su ubicación.
- Rastreo de Distancia: Iniciar el seguimiento de la distancia que el usuario ha caminado/corrido al hacer clic en un botón y detenerlo al presionar otro botón.
Problemas Comunes
Al implementar esta funcionalidad, es posible que te encuentres con problemas, como:
- Inexactitud en la distancia calculada: A veces, la distancia que se muestra puede no ser precisa.
- Incremento de la distancia mientras se está detenido: El sistema podría seguir sumando distancia aunque el usuario no se esté moviendo.
Solución Propuesta
A continuación, se detalla el código que puedes utilizar para implementar el rastreo de distancia y algunas mejoras que se pueden realizar:
const MIN_MOVEMENT_THRESHOLD = 1; // Ignorar movimientos menores de 1 metro
// Fórmula de Haversine para calcular distancia en metros
const getDistance = (lat1, lon1, lat2, lon2) => {
const R = 6371000; // Radio de la Tierra en metros
const toRad = angle => (angle * Math.PI) / 180;
const dLat = toRad(lat2 - lat1);
const dLon = toRad(lon2 - lon1);
const a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c;
};
export function RouteMapScreen({ route }) {
const mapInView = route.params.chosenMap;
const [isTracking, setIsTracking] = useState(false);
const [totalDistance, setTotalDistance] = useState(0);
const lastLocationRef = useRef(null); // Persistir ubicación previa
useEffect(() => {
let locationSubscription = null;
const startTracking = async () => {
let { status } = await Location.requestForegroundPermissionsAsync();
if (status !== "granted") {
console.log("Permiso para acceder a la ubicación denegado");
return;
}
locationSubscription = await Location.watchPositionAsync(
{
accuracy: Location.Accuracy.Highest,
distanceInterval: 1,
timeInterval: 1000
},
(location) => {
// Ignorar actualizaciones cuando está detenido o moviéndose lentamente
if (location.coords.speed !== null && location.coords.speed < 0.5) {
return;
}
if (lastLocationRef.current) {
const distance = getDistance(
lastLocationRef.current.coords.latitude,
lastLocationRef.current.coords.longitude,
location.coords.latitude,
location.coords.longitude
);
// Solo añadir la distancia si es mayor que el umbral
if (distance > MIN_MOVEMENT_THRESHOLD) {
setTotalDistance((prev) => prev + distance);
}
}
lastLocationRef.current = location;
}
);
};
if (isTracking) {
startTracking();
}
return () => {
if (locationSubscription) {
locationSubscription.remove();
}
};
}, [isTracking]);
return (
<>
<View style={styles.mapActions}>
<Text>Run</Text>
<Pressable android_ripple={{ color: "darkred" }} onPress={() => setIsTracking(false)}>
<Text>END</Text>
</Pressable>
</View>
<Text>Distance: {totalDistance.toFixed(2)} meters</Text>
<View style={styles.mapArea}></View>
<Pressable android_ripple={{ color: "darkred" }} onPress={() => setIsTracking(true)}>
<Text>START</Text>
</Pressable>
</>
);
}
Mejoras Clave
- Métrica de Movimiento: Se utiliza un umbral mínimo (
MIN_MOVEMENT_THRESHOLD
) para ignorar movimientos que no son significativos. - Control de Velocidad: Asegúrate de que el cálculo de la distancia se realice solo si el usuario está en movimiento significativo.
Aplicando estos conceptos y el código proporcionado, podrás rastrear de manera efectiva la distancia recorrida por un usuario en una aplicación de React Expo. Asegúrate de probar en diferentes entornos para validar la precisión del seguimiento.