Maison > interface Web > js tutoriel > Fonctions essentielles pour les applications basées sur la localisation dans React Native à l'aide des API Google Maps

Fonctions essentielles pour les applications basées sur la localisation dans React Native à l'aide des API Google Maps

Linda Hamilton
Libérer: 2024-12-07 20:15:14
original
148 Les gens l'ont consulté

Essential Functions for Location-Based Apps in React Native Using Google Maps APIs

Dans les applications centrées sur la localisation, la mise en œuvre de fonctionnalités robustes pour la géolocalisation, l'itinéraire et l'estimation des tarifs est cruciale. Voici une liste des principaux utilitaires qui peuvent être mis en œuvre :


? 1. Récupération de la latitude, de la longitude et de l'adresse

  • Fonction : getLatLong(placeId)
  • Objectif : récupère les coordonnées géographiques (latitude et longitude) et l'adresse d'un placeId donné à l'aide de l'API Google Places.
  • Cas d'utilisation : utile pour identifier des emplacements exacts en fonction d'un placeId unique (par exemple, pour les marqueurs de carte).
  • Exemple : Pour un placeId, la fonction renvoie la latitude, la longitude et l'adresse dans un format structuré.

? 2. Géocodage inversé

  • Fonction : reverseGeocode(latitude, longitude)
  • Objectif : convertit les coordonnées géographiques en une adresse lisible par l'homme à l'aide de l'API Google Geocoding.
  • Cas d'utilisation : affichez l'adresse de l'emplacement sélectionné ou les coordonnées GPS d'un utilisateur.
  • Exemple : fournissez une adresse conviviale telle que "Sydney NSW, Australie" pour les coordonnées données.

? 3. Placer des suggestions de saisie semi-automatique

  • Fonction : getPlacesSuggestions(requête)
  • Objectif : récupère les suggestions de localisation en fonction des entrées de l'utilisateur à l'aide de l'API de saisie semi-automatique de Google Places.
  • Cas d'utilisation : améliore la fonctionnalité de recherche en fournissant une liste déroulante de suggestions d'emplacement.
  • Exemple : suggère "Sydney Opera House" ou "Sydney Airport" lorsque l'utilisateur saisit "Sydney".

? 4. Calcul de la distance

  • Fonction : calculerDistance(lat1, lon1, lat2, lon2)
  • Objectif : Calcule la distance entre deux points géographiques à l'aide de la formule Haversine.
  • Cas d'utilisation : idéal pour estimer la distance entre la position actuelle d'un utilisateur et sa destination.
  • Exemple : calcule 20,56 kilomètres comme distance entre deux ensembles de coordonnées.

? 5. Estimation dynamique des tarifs

  • Fonction : calculer le tarif (distance)
  • Objectif : calcule les tarifs pour différents types de véhicules (vélo, voiture, cabine économique, cabine premium) en fonction de la distance parcourue.
  • Cas d'utilisation : utile pour les applications de covoiturage ou les services de livraison afin d'afficher dynamiquement les estimations de tarifs.
  • Exemple : fournit des détails tarifaires tels que 50 ₹ pour un vélo ou 100 ₹ pour un taxi économique pour un trajet de 10 km.

6. Générer des itinéraires fluides à l'aide des courbes de Bézier

  • Fonction : getPoints(places)
  • Objectif : crée un itinéraire fluide et visuellement attrayant entre deux points à l'aide de courbes quadratiques de Bézier.
  • Cas d'utilisation : ajoute une visualisation soignée des itinéraires sur les cartes pour les applications de navigation.
  • Exemple : génère 100 points le long d'une courbe entre deux emplacements pour créer une polyligne lisse.

? 7. Gestion des icônes de véhicules

  • Utilitaire : VehicleIcons
  • Objectif : mappe les types de véhicules (par exemple, vélo, auto, cabEconomy) sur leurs icônes respectives pour une interface utilisateur cohérente et dynamique.
  • Cas d'utilisation : affichez les icônes appropriées en fonction du type de véhicule sélectionné dans les applications de covoiturage ou de livraison.
  • Exemple : Récupère dynamiquement l'icône d'un "vélo" ou d'un "cabPremium".

Code complet :

import axios from "axios";
import { useUserStore } from "@/store/userStore";

/**
 * Fetch latitude, longitude, and address details for a given place ID.
 * @param {string} placeId - The unique identifier for a place (e.g., "ChIJN1t_tDeuEmsRUsoyG83frY4").
 * @returns {Promise<{latitude: number, longitude: number, address: string}>} Location data.
 * Example response:
 * {
 *   latitude: -33.8670522,
 *   longitude: 151.1957362,
 *   address: "Sydney NSW, Australia"
 * }
 */
export const getLatLong = async (placeId: string) => {
    try {
        const response = await axios.get("https://maps.googleapis.com/maps/api/place/details/json", {
            params: {
                placeid: placeId, // Place ID for the location
                key: process.env.EXPO_PUBLIC_MAP_API_KEY, // API key for authentication
            },
        });

        const data = response.data;

        // Validate response status and extract required fields
        if (data.status === "OK" && data.result) {
            const location = data.result.geometry.location; // Get latitude and longitude
            const address = data.result.formatted_address; // Get formatted address

            return {
                latitude: location.lat,
                longitude: location.lng,
                address: address,
            };
        } else {
            // Handle API response errors
            throw new Error("Unable to fetch location details");
        }
    } catch (error) {
        // Catch and throw any request or processing errors
        throw new Error("Unable to fetch location details");
    }
};

/**
 * Reverse geocode latitude and longitude to fetch the address.
 * @param {number} latitude - Latitude of the location (e.g., -33.8670522).
 * @param {number} longitude - Longitude of the location (e.g., 151.1957362).
 * @returns {Promise<string>} Address of the location.
 * Example response: "Sydney NSW, Australia"
 */
export const reverseGeocode = async (latitude: number, longitude: number) => {
    try {
        const response = await axios.get(
            `https://maps.googleapis.com/maps/api/geocode/json?latlng=${latitude},${longitude}&key=${process.env.EXPO_PUBLIC_MAP_API_KEY}`
        );

        // Check if the response status is OK and extract the address
        if (response.data.status === "OK") {
            const address = response.data.results[0].formatted_address;
            return address; // Return the formatted address
        } else {
            // Log failure details and return an empty string
            console.log("Geocoding failed: ", response.data.status);
            return "";
        }
    } catch (error) {
        // Handle any request or processing errors
        console.log("Error during reverse geocoding: ", error);
        return "";
    }
};

/**
 * Extract relevant place data from API response.
 * @param {Array} data - Array of place predictions from the API.
 * @returns {Array<{place_id: string, title: string, description: string}>} Processed place data.
 * Example response:
 * [
 *   { place_id: "xyz123", title: "Sydney Opera House", description: "Iconic performing arts venue in Sydney" }
 * ]
 */
function extractPlaceData(data: any) {
    return data.map((item: any) => ({
        place_id: item.place_id, // Unique identifier for the place
        title: item.structured_formatting.main_text, // Main title of the place
        description: item.description, // Detailed description
    }));
}


/**
 * Fetch autocomplete suggestions for places based on a query.
 * @param {string} query - User's input for place suggestions (e.g., "Sydney").
 * @returns {Promise<Array>} List of place suggestions.
 * Example response:
 * [
 *   { place_id: "xyz123", title: "Sydney Opera House", description: "Iconic performing arts venue in Sydney" }
 * ]
 */
export const getPlacesSuggestions = async (query: string) => {
    const { location } = useUserStore.getState(); // Get user's current location from the store
    try {
        const response = await axios.get(
            `https://maps.googleapis.com/maps/api/place/autocomplete/json`, {
            params: {
                input: query, // Query string for suggestions
                location: `${location?.latitude},${location?.longitude}`, // Use current location for proximity
                radius: 50000, // Search within a 50km radius
                components: "country:IN", // Restrict results to India
                key: process.env.EXPO_PUBLIC_MAP_API_KEY, // API key for authentication
            }
        }
        );

        // Process and return extracted place data
        return extractPlaceData(response.data.predictions);
    } catch (error) {
        // Log errors and return an empty array
        console.error("Error fetching autocomplete suggestions:", error);
        return [];
    }
};

/**
 * Calculate the distance between two geographic coordinates using the Haversine formula.
 * @param {number} lat1 - Latitude of the first point (e.g., 28.7041).
 * @param {number} lon1 - Longitude of the first point (e.g., 77.1025).
 * @param {number} lat2 - Latitude of the second point (e.g., 28.5355).
 * @param {number} lon2 - Longitude of the second point (e.g., 77.3910).
 * @returns {number} Distance in kilometers.
 * Example response: 20.56
 */
export const calculateDistance = (lat1: number, lon1: number, lat2: number, lon2: number) => {
    const R = 6371; // Earth's radius in kilometers
    const dLat = (lat2 - lat1) * (Math.PI / 180); // Latitude difference in radians
    const dLon = (lon2 - lon1) * (Math.PI / 180); // Longitude difference in radians
    const a =
        Math.sin(dLat / 2) * Math.sin(dLat / 2) +
        Math.cos(lat1 * (Math.PI / 180)) * Math.cos(lat2 * (Math.PI / 180)) *
        Math.sin(dLon / 2) * Math.sin(dLon / 2); // Haversine formula
    const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); // Angular distance
    return R * c; // Distance in kilometers
};

/**
 * Calculate fare for different vehicle types based on the distance traveled.
 * @param {number} distance - Distance traveled in kilometers (e.g., 15).
 * @returns {Object} Fare breakdown for each vehicle type.
 * Example response:
 * {
 *   bike: 50,
 *   auto: 60,
 *   cabEconomy: 100,
 *   cabPremium: 150
 * }
 */
export const calculateFare = (distance: number) => {
    // Fare rates for different vehicle types
    const rateStructure = {
        bike: { baseFare: 10, perKmRate: 5, minimumFare: 25 },
        auto: { baseFare: 15, perKmRate: 7, minimumFare: 30 },
        cabEconomy: { baseFare: 20, perKmRate: 10, minimumFare: 50 },
        cabPremium: { baseFare: 30, perKmRate: 15, minimumFare: 70 },
    };

    // Helper function to calculate fare
    const fareCalculation = (baseFare: number, perKmRate: number, minimumFare: number) => {
        const calculatedFare = baseFare + (distance * perKmRate); // Calculate fare based on distance
        return Math.max(calculatedFare, minimumFare); // Ensure the fare meets the minimum
    };

    // Return fare details for each vehicle type
    return {
        bike: fareCalculation(rateStructure.bike.baseFare, rateStructure.bike.perKmRate, rateStructure.bike.minimumFare),
        auto: fareCalculation(rateStructure.auto.baseFare, rateStructure.auto.perKmRate, rateStructure.auto.minimumFare),
        cabEconomy: fareCalculation(rateStructure.cabEconomy.baseFare, rateStructure.cabEconomy.perKmRate, rateStructure.cabEconomy.minimumFare),
        cabPremium: fareCalculation(rateStructure.cabPremium.baseFare, rateStructure.cabPremium.perKmRate, rateStructure.cabPremium.minimumFare),
    };
};


/**
 * Generate points along a quadratic Bezier curve between two points with a control point.
 * @param {Array<number>} p1 - The starting point of the curve [latitude, longitude] (e.g., [28.7041, 77.1025]).
 * @param {Array<number>} p2 - The ending point of the curve [latitude, longitude] (e.g., [28.5355, 77.3910]).
 * @param {Array<number>} controlPoint - The control point for the curve [latitude, longitude] (e.g., [28.6, 77.25]).
 * @param {number} numPoints - The number of points to generate along the curve.
 * @returns {Array<{latitude: number, longitude: number}>} Array of coordinates forming the curve.
 * Example response:
 * [
 *   { latitude: 28.7041, longitude: 77.1025 },
 *   { latitude: 28.635, longitude: 77.175 },
 *   { latitude: 28.5355, longitude: 77.3910 }
 * ]
 */
function quadraticBezierCurve(p1: any, p2: any, controlPoint: any, numPoints: any) {
    const points = [];
    const step = 1 / (numPoints - 1); // Step size for dividing the curve

    for (let t = 0; t <= 1; t += step) {
        const x =
            (1 - t) ** 2 * p1[0] + // Contribution of starting point
            2 * (1 - t) * t * controlPoint[0] + // Contribution of control point
            t ** 2 * p2[0]; // Contribution of ending point
        const y =
            (1 - t) ** 2 * p1[1] +
            2 * (1 - t) * t * controlPoint[1] +
            t ** 2 * p2[1];
        const coord = { latitude: x, longitude: y }; // Store as coordinate object
        points.push(coord); // Add to the points array
    }

    return points; // Return array of points forming the curve
}

/**
 * Calculate the control point for a quadratic Bezier curve between two points.
 * @param {Array<number>} p1 - The starting point [latitude, longitude].
 * @param {Array<number>} p2 - The ending point [latitude, longitude].
 * @returns {Array<number>} The control point [latitude, longitude].
 * Example response: [28.6, 77.25]
 */
const calculateControlPoint = (p1: any, p2: any) => {
    const d = Math.sqrt((p2[0] - p1[0]) ** 2 + (p2[1] - p1[1]) ** 2); // Distance between p1 and p2
    const scale = 1; // Scale factor for bending the curve
    const h = d * scale; // Adjusted distance from midpoint
    const w = d / 2; // Halfway between points
    const x_m = (p1[0] + p2[0]) / 2; // Midpoint x
    const y_m = (p1[1] + p2[1]) / 2; // Midpoint y

    const x_c =
        x_m + ((h * (p2[1] - p1[1])) / (2 * Math.sqrt((p2[0] - p1[0]) ** 2 + (p2[1] - p1[1]) ** 2))) * (w / d);
    const y_c =
        y_m - ((h * (p2[0] - p1[0])) / (2 * Math.sqrt((p2[0] - p1[0]) ** 2 + (p2[1] - p1[1]) ** 2))) * (w / d);

    return [x_c, y_c]; // Return calculated control point
};

/**
 * Generate Bezier curve points for given locations.
 * @param {Array<{latitude: number, longitude: number}>} places - Array containing at least two points.
 * @returns {Array<{latitude: number, longitude: number}>} Array of coordinates forming the curve.
 * Example response:
 * [
 *   { latitude: 28.7041, longitude: 77.1025 },
 *   { latitude: 28.635, longitude: 77.175 },
 *   { latitude: 28.5355, longitude: 77.3910 }
 * ]
 */
export const getPoints = (places: any) => {
    const p1 = [places[0].latitude, places[0].longitude]; // Starting point
    const p2 = [places[1].latitude, places[1].longitude]; // Ending point
    const controlPoint = calculateControlPoint(p1, p2); // Calculate the control point

    return quadraticBezierCurve(p1, p2, controlPoint, 100); // Generate 100 points along the curve
};

/**
 * Map of vehicle types to their respective icons.
 * @type {Record<'bike' | 'auto' | 'cabEconomy' | 'cabPremium', { icon: any }>}
 * Example usage:
 * vehicleIcons.bike.icon -> Path to bike icon
 */
export const vehicleIcons: Record<'bike' | 'auto' | 'cabEconomy' | 'cabPremium', { icon: any }> = {
    bike: { icon: require('@/assets/icons/bike.png') }, // Icon for bike
    auto: { icon: require('@/assets/icons/auto.png') }, // Icon for auto
    cabEconomy: { icon: require('@/assets/icons/cab.png') }, // Icon for economy cab
    cabPremium: { icon: require('@/assets/icons/cab_premium.png') }, // Icon for premium cab
};
Copier après la connexion

? Conclusion

Ces utilitaires permettent aux développeurs de :

  1. Intégrez des services transparents basés sur la localisation.
  2. Améliorez l'expérience utilisateur avec des données en temps réel et des visuels intuitifs.
  3. Créez des applications React Native évolutives et dynamiques avec les API Google Maps.

En combinant la géolocalisation, la visualisation d'itinéraires et l'estimation des tarifs, vous pouvez améliorer considérablement les fonctionnalités de votre application et offrir plus de valeur à vos utilisateurs.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal