الحصول على مصفوفة مسار

المطوّرون في المنطقة الاقتصادية الأوروبية

مصفوفة المسارات هي مصفوفة ثنائية الأبعاد لمعلومات المسارات، حيث تتوافق الصفوف مع نقاط الانطلاق وتتوافق الأعمدة مع الوجهات. عند توفير قائمة بنقاط الانطلاق والوجهات، تحتسب فئة "مصفوفة المسارات" المسافة والمدة لمسار يبدأ من كل نقطة انطلاق وينتهي عند كل وجهة. استخدِم فئة مصفوفة المسارات لحساب المسافة والمدة لمسار يتضمّن نقاط انطلاق ووجهات متعددة.

الاطّلاع على الرمز المصدر للمثال الكامل

يوضّح هذا المثال كيفية استخدام فئة مصفوفة المسارات لاحتساب المسافات والمدد للسفر بين نقاط انطلاق ووجهات متعددة.

TypeScript

// Initialize and add the map.
let map: google.maps.Map;
const markers: google.maps.marker.AdvancedMarkerElement[] = [];
const center = { lat: 51.55, lng: -1.8 };

async function init(): Promise<void> {
    //  Request the needed libraries.
    const [
        { Map },
        { Place },
        { AdvancedMarkerElement, PinElement },
        { RouteMatrix },
        { LatLngBounds, UnitSystem },
    ] = await Promise.all([
        google.maps.importLibrary('maps'),
        google.maps.importLibrary('places'),
        google.maps.importLibrary('marker'),
        google.maps.importLibrary('routes'),
        google.maps.importLibrary('core'),
    ]);

    const bounds = new LatLngBounds();

    map = new Map(document.getElementById('map')!, {
        zoom: 8,
        center,
        mapId: 'DEMO_MAP_ID',
    });

    // Build the request using Place instances.
    const origin1 = new Place({
        id: 'ChIJ83WZp86p2EcRbMrkYqGncBQ', // Greenwich, London, UK
    });
    const origin2 = new Place({
        id: 'ChIJCSkVvleJc0gR8HHaTGpajKc', // Southampton, UK
    });
    const destinationA = new Place({
        id: 'ChIJYdizgWaDcUgRH9eaSy6y5I4', // Bristol, UK
    });
    const destinationB = new Place({
        id: 'ChIJ9VPsNNQCbkgRDmeGZdsGNBQ', // Cardiff, UK
    });

    await Promise.all([
        origin1.fetchFields({ fields: ['location', 'displayName'] }),
        origin2.fetchFields({ fields: ['location', 'displayName'] }),
        destinationA.fetchFields({ fields: ['location', 'displayName'] }),
        destinationB.fetchFields({ fields: ['location', 'displayName'] }),
    ]);

    const destinations = [destinationA, destinationB];
    const origins = [origin1, origin2];
    const request: google.maps.routes.ComputeRouteMatrixRequest = {
        origins,
        destinations,
        travelMode: 'DRIVING',
        units: UnitSystem.METRIC,
        fields: ['distanceMeters', 'durationMillis', 'condition'],
    };

    // Show the request.
    document.getElementById('request')!.innerText = JSON.stringify(
        request,
        null,
        2
    );

    // Get the RouteMatrix response.
    const response = await RouteMatrix.computeRouteMatrix(request);

    // Show the response.
    document.getElementById('response')!.innerText = JSON.stringify(
        response,
        null,
        2
    );

    // Add markers for the origins.
    for (const origin of origins) {
        if (origin.location) {
            const pin = new PinElement({
                glyphText: 'O',
                glyphColor: 'white',
                background: '#137333',
                borderColor: 'white',
            });
            const marker = new AdvancedMarkerElement({
                map,
                position: origin.location,
                title: `Origin: ${origin.displayName}`,
            });
            marker.append(pin);
            markers.push(marker);
            bounds.extend(origin.location);
        }
    }

    // Add markers for the destinations.
    for (const destination of destinations) {
        if (destination.location) {
            const pin = new PinElement({
                glyphText: 'D',
                glyphColor: 'white',
                background: '#C5221F',
                borderColor: 'white',
            });

            const marker = new AdvancedMarkerElement({
                map,
                position: destination.location,
                content: pin,
                title: `Destination: ${destination.displayName ?? 'Unknown'}`,
            });

            markers.push(marker);
            bounds.extend(destination.location);
        }
    }

    // Fit the map to the bounds of all markers.
    map.fitBounds(bounds);
}

void init();

JavaScript

// Initialize and add the map.
let map;
const markers = [];
const center = { lat: 51.55, lng: -1.8 };

async function init() {
    //  Request the needed libraries.
    const [
        { Map },
        { Place },
        { AdvancedMarkerElement, PinElement },
        { RouteMatrix },
        { LatLngBounds, UnitSystem },
    ] = await Promise.all([
        google.maps.importLibrary('maps'),
        google.maps.importLibrary('places'),
        google.maps.importLibrary('marker'),
        google.maps.importLibrary('routes'),
        google.maps.importLibrary('core'),
    ]);

    const bounds = new LatLngBounds();

    map = new Map(document.getElementById('map'), {
        zoom: 8,
        center,
        mapId: 'DEMO_MAP_ID',
    });

    // Build the request using Place instances.
    const origin1 = new Place({
        id: 'ChIJ83WZp86p2EcRbMrkYqGncBQ', // Greenwich, London, UK
    });
    const origin2 = new Place({
        id: 'ChIJCSkVvleJc0gR8HHaTGpajKc', // Southampton, UK
    });
    const destinationA = new Place({
        id: 'ChIJYdizgWaDcUgRH9eaSy6y5I4', // Bristol, UK
    });
    const destinationB = new Place({
        id: 'ChIJ9VPsNNQCbkgRDmeGZdsGNBQ', // Cardiff, UK
    });

    await Promise.all([
        origin1.fetchFields({ fields: ['location', 'displayName'] }),
        origin2.fetchFields({ fields: ['location', 'displayName'] }),
        destinationA.fetchFields({ fields: ['location', 'displayName'] }),
        destinationB.fetchFields({ fields: ['location', 'displayName'] }),
    ]);

    const destinations = [destinationA, destinationB];
    const origins = [origin1, origin2];
    const request = {
        origins,
        destinations,
        travelMode: 'DRIVING',
        units: UnitSystem.METRIC,
        fields: ['distanceMeters', 'durationMillis', 'condition'],
    };

    // Show the request.
    document.getElementById('request').innerText = JSON.stringify(
        request,
        null,
        2
    );

    // Get the RouteMatrix response.
    const response = await RouteMatrix.computeRouteMatrix(request);

    // Show the response.
    document.getElementById('response').innerText = JSON.stringify(
        response,
        null,
        2
    );

    // Add markers for the origins.
    for (const origin of origins) {
        if (origin.location) {
            const pin = new PinElement({
                glyphText: 'O',
                glyphColor: 'white',
                background: '#137333',
                borderColor: 'white',
            });
            const marker = new AdvancedMarkerElement({
                map,
                position: origin.location,
                title: `Origin: ${origin.displayName}`,
            });
            marker.append(pin);
            markers.push(marker);
            bounds.extend(origin.location);
        }
    }

    // Add markers for the destinations.
    for (const destination of destinations) {
        if (destination.location) {
            const pin = new PinElement({
                glyphText: 'D',
                glyphColor: 'white',
                background: '#C5221F',
                borderColor: 'white',
            });

            const marker = new AdvancedMarkerElement({
                map,
                position: destination.location,
                content: pin,
                title: `Destination: ${destination.displayName ?? 'Unknown'}`,
            });

            markers.push(marker);
            bounds.extend(destination.location);
        }
    }

    // Fit the map to the bounds of all markers.
    map.fitBounds(bounds);
}

void init();

CSS

/*
 * Always set the map height explicitly to define the size of the div element
 * that contains the map.
 */
/* Optional: Makes the sample page fill the window. */
html,
body {
    height: 100%;
    margin: 0;
    padding: 0;
}

#container {
    height: 100%;
    display: flex;
}

#sidebar {
    flex-basis: 15rem;
    flex-grow: 1;
    padding: 1rem;
    max-width: 30rem;
    height: 100%;
    box-sizing: border-box;
    overflow: auto;
}

#map {
    flex-basis: 0;
    flex-grow: 4;
    height: 100%;
}

#sidebar {
    flex-direction: column;
}

HTML

<html>
    <head>
        <title>Route matrix</title>

        <link rel="stylesheet" type="text/css" href="./style.css" />
        <script type="module" src="./index.js"></script>
        <script>
            // prettier-ignore
            (g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({
                key: "GOOGLE_MAPS_API_KEY"
            });
        </script>
    </head>
    <body>
        <div id="container">
            <div id="map"></div>
            <div id="sidebar">
                <h3 style="flex-grow: 0">Request</h3>
                <pre style="flex-grow: 1" id="request"></pre>
                <h3 style="flex-grow: 0">Response</h3>
                <pre style="flex-grow: 1" id="response"></pre>
            </div>
        </div>
    </body>
</html>

تجربة عيّنة

حدود الطلبات

تفرض طريقة computeRouteMatrix الحدود التالية على الطلبات الخاصة بنقاط المسار التي تستخدم مثيلات العناوين أو الأماكن، وعلى العناصر. العناصر هي المسارات بين كل نقطة انطلاق ووجهة في مصفوفة المسارات، وبالتالي يكون عدد العناصر هو عدد نقاط الانطلاق مضروبًا في عدد الوجهات. على سبيل المثال، إذا كان لديك 10 نقاط انطلاق و10 وجهات، سيكون لديك 100 عنصر:

  • لا يمكن أن يتجاوز عدد العناصر 625 للمسارات التي ليست مسارات TRANSIT.
  • في حال تحديد مسار TRANSIT، لا يمكن أن يتجاوز عدد العناصر 100 عنصر.
  • إذا حدّدت TRAFFIC_AWARE_OPTIMAL، لا يمكن أن يتجاوز عدد العناصر 100 عنصر.
  • إذا حدّدت نقاط الانطلاق أو الوجهات باستخدام العناوين أو مثيلات الأماكن، يمكنك تحديد ما يصل إلى 50 نقطة انطلاق أو وجهة إجمالاً بهذه الطريقة.

لمزيد من التفاصيل، يُرجى الاطّلاع على الحصول على مسار نقل عام.

مثال على طلب مصفوفة المسارات

يعرض المثال التالي ComputeRouteMatrixRequest. ينفّذ هذا المثال ما يلي:

  • يعرض هذا المثال تحديد مصفوفة من نقطتَي انطلاق ونقطتَي وجهة على المسار. تحسب الطريقة مسارًا من كل نقطة انطلاق إلى كل وجهة، وبالتالي يحتوي الردّ على أربعة مسارات.
    في المصفوفة، يكون العنصر الأول في الفهرس 0، والثاني في الفهرس 1، وهكذا.
  • يحدّد الحقول المطلوب عرضها. في هذا المثال، تم ضبط الطلب لعرض durationMillis وdistanceMeters وcondition لكل مسار.

TypeScript

const destinations = [destinationA, destinationB];
const origins = [origin1, origin2];
const request: google.maps.routes.ComputeRouteMatrixRequest = {
    origins,
    destinations,
    travelMode: 'DRIVING',
    units: UnitSystem.METRIC,
    fields: ['distanceMeters', 'durationMillis', 'condition'],
};

JavaScript

const destinations = [destinationA, destinationB];
const origins = [origin1, origin2];
const request = {
    origins,
    destinations,
    travelMode: 'DRIVING',
    units: UnitSystem.METRIC,
    fields: ['distanceMeters', 'durationMillis', 'condition'],
};

يحتوي الردّ على المسارات الأربعة المحتملة لمجموعة جميع نقاط المسار الخاصة بنقطة الانطلاق والوجهة، كما هو موضّح في المثال التالي:

"matrix": {
  "rows": [
    {
      "items": [
        {
          "condition": "ROUTE_EXISTS",
          "distanceMeters": 202587,
          "durationMillis": 10040000
        },
        {
          "condition": "ROUTE_EXISTS",
          "distanceMeters": 252734,
          "durationMillis": 12240000
        }
      ]
    },
    {
      "items": [
        {
          "condition": "ROUTE_EXISTS",
          "distanceMeters": 166135,
          "durationMillis": 6596000
        },
        {
          "condition": "ROUTE_EXISTS",
          "distanceMeters": 216282,
          "durationMillis": 8797000
        }
      ]
    }
  ]
}
    

حدِّد كل مسار في النتيجة باستخدام فهرس نقطة الانطلاق والوجهة للعثور على RouteMatrixItem المقابل في الصفيف الثنائي الأبعاد. على سبيل المثال، سيكون RouteMatrixItem الذي يصف المسار المحسوب من نقطة الانطلاق في الفهرس 1 والوجهة 0 في الطلب في العنصر الثاني من مصفوفة RouteMatrix.rows والعنصر الأول من مصفوفة RouteMatrixRow.items.

يوضّح مقتطف الرمز التالي كيفية تحديد RouteMatrixItem للعثور على المسار لنقطة انطلاق ووجهة معيّنتَين:

// Find the route for origin 'x' and destination 'y'.
const {matrix} = await RouteMatrix.computeRouteMatrix(request);
const myRouteMatrixItem = matrix.rows[x].items[y];
    

اختيار الحقول المطلوب عرضها

عند طلب مصفوفة مسارات، يجب استخدام قناع حقل لتحديد المعلومات التي يجب أن يعرضها الردّ.

يضمن استخدام قناع الحقل أيضًا عدم طلب بيانات غير ضرورية، ما يساعد بدوره في تقليل وقت استجابة الطلب وتجنُّب عرض معلومات لا يحتاجها نظامك.

حدِّد قائمة الحقول التي تحتاج إليها من خلال ضبط السمة ComputeRoutesMatrixRequest.fields، كما هو موضّح في المقتطف التالي:

fields: ['durationMillis', 'distanceMeters', 'condition'],
    

تحديد أقنعة الحقول المطلوب استخدامها

في ما يلي كيفية تحديد الحقول التي تريد استخدامها وإنشاء أقنعة الحقول لها:

  1. طلب جميع الحقول باستخدام قناع حقل ['*']
  2. اطّلِع على التسلسل الهرمي للحقول في الفئة RouteMatrixItem للحقول التي تريدها.
  3. أنشئ أقنعة الحقول باستخدام التسلسل الهرمي للحقول المعروضة في الخطوة السابقة، وذلك باستخدام التنسيق التالي:

    topLevelField[.secondLevelField][.thirdLevelField][...]

على سبيل المثال، بالنسبة إلى RouteMatrixItem:

  "travelAdvisory": {
    "fuelConsumptionMicroliters": 0,
    "tollInfo": {
      "estimatedPrices": [
        {
          "currencyCode": "USD",
          "units": 4,
          "nanos": 400000000
        }
      ]
    }
  },
    

إذا أردت عرض الحقل tollInfo فقط لـ RouteMatrixItem، يكون قناع الحقل على النحو التالي:

fields: ['travelAdvisory.tollInfo']

إذا أردت بدلاً من ذلك طلب استهلاك الوقود المقدَّر، يكون قناع الحقل على النحو التالي:

fields: ['travelAdvisory.fuelConsumptionMicroliters']

إذا أردت طلب كليهما، يكون قناع الحقل على النحو التالي:

fields: ['travelAdvisory.fuelConsumptionMicroliters', 'travelAdvisory.tollInfo']

وإذا أردت طلب المجموعة الكاملة من التحذيرات بشأن السفر، يكون قناع الحقل على النحو التالي:

fields: ['travelAdvisory']

طلب مصفوفة مسارات النقل العام

يمكنك الحصول على مصفوفة مسارات نقل عام تستخدم خيارات النقل العام المتاحة في المنطقة. قد تشمل خيارات النقل العام الحافلات ومترو الأنفاق والقطارات وغيرها. لطلب مصفوفة مسارات النقل العام:

  • يجب ضبط قيمة travelMode على TRANSIT
  • اطلب الحقل travelAdvisory.

مزيد من المعلومات عن مسارات النقل العام