ホームページ > ウェブフロントエンド > jsチュートリアル > Google Maps API を使用した React Native の位置情報ベースのアプリの必須機能

Google Maps API を使用した React Native の位置情報ベースのアプリの必須機能

Linda Hamilton
リリース: 2024-12-07 20:15:14
オリジナル
146 人が閲覧しました

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

位置中心のアプリケーションでは、地理位置情報、ルーティング、運賃見積りのための堅牢な機能を実装することが重要です。実装できる主要なユーティリティの内訳は次のとおりです:


? 1.緯度、経度、住所の取得

  • 関数: getLatLong(placeId)
  • 目的: Google Places API を使用して、指定された placeId の地理座標 (緯度と経度) と住所を取得します。
  • ユースケース: 一意の placeId に基づいて正確な位置を識別するのに役立ちます (地図マーカーなど)。
  • : placeId の場合、関数は緯度、経度、住所を構造化形式で返します。

? 2.逆ジオコーディング

  • 関数: reverseGeocode(緯度、経度)
  • 目的: Google Geocoding API を使用して、地理座標を人間が判読できる住所に変換します。
  • 使用例: ユーザーが選択した場所の住所または GPS 座標を表示します。
  • : 指定された座標に対して、「ニューサウスウェールズ州シドニー、オーストラリア」のようなわかりやすい住所を指定します。

? 3.オートコンプリートの候補を配置

  • 関数: getPlacesSuggestions(クエリ)
  • 目的: Google Places Autocomplete API を使用して、ユーザー入力に基づいて場所の候補を取得します。
  • ユースケース: 場所の候補のドロップダウンを提供することで検索機能を強化します。
  • : ユーザーが「シドニー」と入力すると、「シドニー オペラ ハウス」または「シドニー空港」が提案されます。

? 4.距離の計算

  • 関数: CalculateDistance(lat1, lon1, lat2, lon2)
  • 目的: ハーバーサイン公式を使用して、2 つの地理的点間の距離を計算します。
  • ユースケース: ユーザーの現在位置と目的地の間の距離を推定するのに最適です。
  • : 2 つの座標セット間の距離として 20.56 キロメートルを計算します。

? 5.動的運賃見積り

  • 関数: 運賃計算(距離)
  • 目的: 走行距離に基づいて、さまざまな車両タイプ (自転車、自動車、エコノミー タクシー、プレミアム タクシー) の運賃を計算します。
  • ユースケース: 配車アプリや配送サービスで運賃の見積もりを動的に表示するのに役立ちます。
  • : 10 km の旅行の場合、自転車の場合は ₹50、エコノミー タクシーの場合は ₹100 などの運賃の詳細が表示されます。

6.ベジェ曲線を使用した滑らかなルートの生成

  • 関数: getPoints(場所)
  • 目的: 二次ベジェ曲線を使用して、2 点間の滑らかで視覚的に魅力的なルートを作成します。
  • ユースケース: ナビゲーション アプリの地図上に洗練されたルートの視覚化を追加します。
  • : 2 つの位置間の曲線に沿って 100 個のポイントを生成し、滑らかなポリラインを作成します。

? 7.車両アイコン管理

  • ユーティリティ: vehicleIcons
  • 目的: 車両タイプ (例: 自転車、自動車、タクシーエコノミー) をそれぞれのアイコンにマッピングして、一貫性のある動的な UI を実現します。
  • ユースケース: 配車アプリや配達アプリで、選択した車両タイプに基づいて適切なアイコンを表示します。
  • : 「バイク」または「cabPremium」のアイコンを動的に取得します。

完全なコード:

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
};
ログイン後にコピー

? 結論

これらのユーティリティにより、開発者は次のことが可能になります。

  1. シームレスな位置情報ベースのサービスを統合します。
  2. リアルタイム データと直感的なビジュアルでユーザー エクスペリエンスを向上させます。
  3. Google Maps API を使用して、スケーラブルで動的な React Native アプリケーションを構築します。

地理位置情報、ルートの視覚化、運賃見積りを組み合わせることで、アプリの機能を大幅に向上させ、ユーザーにより多くの価値を提供できます。

以上がGoogle Maps API を使用した React Native の位置情報ベースのアプリの必須機能の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート