أنواع الخرائط

اختَر النظام الأساسي: Android iOS JavaScript

يناقش هذا المستند أنواع الخرائط التي يمكنك عرضها باستخدام Maps JavaScript API. تستخدم واجهة برمجة التطبيقات عنصرًا MapType للاحتفاظ بمعلومات حول هذه الخرائط. MapType هي واجهة تحدّد عرض مربعات الخرائط واستخدامها وترجمة أنظمة التنسيق من إحداثيات الشاشة إلى إحداثيات العالم (على الخريطة). ويجب أن يحتوي كل MapType على بضع طرق للتعامل مع استرداد الشاشات وسحبها والخصائص التي تحدّد سلوكها المرئي.

إنّ طريقة العمل الداخلية لأنواع الخرائط ضمن واجهة برمجة تطبيقات JavaScript لتطبيق "خرائط Google" هي موضوع متقدّم. يمكن لمعظم مطوّري البرامج استخدام أنواع الخرائط الأساسية المذكورة أدناه. ومع ذلك، يمكنك أيضًا تعديل عرض تقديمي للأنواع الحالية من الخرائط باستخدام خرائط Google أو تحديد مربّعات الخريطة الخاصة بك باستخدام أنواع الخرائط المخصصة. عند توفير أنواع خرائط مخصّصة، ستحتاج إلى فهم كيفية تعديل سجلّ أنواع الخرائط للخريطة.

أنواع الخرائط الأساسية

هناك أربعة أنواع من الخرائط المتاحة في واجهة برمجة تطبيقات JavaScript للخرائط. بالإضافة إلى أقسام خريطة الطريق "الملوّنة" المألوفة، توفّر Google Maps API أيضًا أنواعًا أخرى من الخرائط.

تتوفر أنواع الخريطة التالية في Maps JavaScript API:

  • يعرض roadmap عرض خريطة الطريق التلقائية. هذا هو نوع الخريطة التلقائي.
  • يعرض satellite صور القمر الصناعي Google Earth.
  • تعرض قناة hybrid مزيجًا من طرق العرض العادية والقمر الصناعي.
  • تعرض terrain خريطة فعلية بناءً على معلومات التضاريس.

يمكنك تعديل نوع الخريطة الذي تستخدمه Map، وذلك من خلال ضبط السمة mapTypeId إما من خلال الإنشاء عن طريق ضبط عنصر Map options أو من خلال استدعاء طريقة setMapTypeId() للخريطة. يتم ضبط السمة التلقائية mapTypeID على roadmap.

إعداد mapTypeId عند الإنشاء:

var myLatlng = new google.maps.LatLng(-34.397, 150.644);
var mapOptions = {
  zoom: 8,
  center: myLatlng,
  mapTypeId: 'satellite'
};
var map = new google.maps.Map(document.getElementById('map'),
    mapOptions);

تعديل mapTypeId ديناميكيًا:

map.setMapTypeId('terrain');

يُرجى العِلم أنّك لا تُحدّد نوع الخريطة على الخريطة مباشرةً، بل بدلاً من ذلك، تضبط السمة mapTypeId للإشارة إلى MapType باستخدام معرّف. تستخدم واجهة برمجة تطبيقات JavaScript للخرائط قاعدة بيانات المسجّلين لنوع الخريطة، كما هو موضّح أدناه، لإدارة هذه المراجع.

صور بزاوية 45 درجة

توفّر واجهة برمجة تطبيقات JavaScript للخرائط صورًا خاصة بزاوية 45 درجة لمواقع جغرافية معيّنة. وتوفّر هذه الصور العالية الدقة منظورات لكل اتجاه من الاتجاه الرأسي (شمالاً وجنوبًا وشرقًا وغربًا). تتوفّر هذه الصور بمستويات تكبير أعلى لأنواع الخرائط المتوافقة.

توضح الصورة التالية منظرًا بزاوية 45 درجة لمدينة نيويورك:

يوفّر نوعَا الخرائط satellite وhybrid صورًا بزاوية 45 بدرجة تكبير عالية (12 درجة أو أكثر) في حال توفّرها. إذا تكبير المستخدم موقعًا تتوفّر فيه هذه الصور، ستغيّر أنواع الخرائط هذه طرق العرض تلقائيًا بالطريقة التالية:

  • يتم استبدال الصور الملتقطة بالقمر الصناعي أو الصور المختلطة بصور تقدّم منظورًا بزاوية 45 درجة في وسط الموقع الجغرافي الحالي. وتكون هذه المشاهدات موجهة تلقائيًا باتجاه الشمال. إذا أجرى المستخدم تصغيرًا، ستظهر مرة أخرى صور القمر الصناعي أو الصور المختلطة التلقائية مرة أخرى. يختلف السلوك استنادًا إلى مستوى التكبير/التصغير وقيمة tilt:
    • يتم عرض الخريطة الأساسية (بين 0 درجة) تلقائيًا بين مستويات التكبير والتصغير 12 و18 ما لم يتم ضبط tilt على 45.
    • على مستويات التكبير أو التصغير 18 درجة أو أكثر، يتم عرض الخريطة الأساسية بزاوية 45 درجة ما لم يتم ضبط tilt على 0.
  • يظهر عنصر التحكّم في التدوير. يوفر عنصر التحكم في التدوير خيارات تتيح للمستخدم تبديل الإمالة وتدوير العرض بزيادات قدرها 90 درجة في أي من الاتجاهَين. لإخفاء عنصر التحكّم في التدوير، اضبط rotateControl على false.

ويؤدي التصغير من نوع خريطة يعرض صورًا بزاوية 45 درجة إلى التراجع عن كل تغيير من هذه التغييرات، ما يؤدي إلى إعادة إنشاء أنواع الخرائط الأصلية.

تفعيل الصور بزاوية 45 درجة وإيقافها

يمكنك إيقاف الصور بزاوية 45 درجة عن طريق طلب setTilt(0) على الكائن Map. لتفعيل عرض الصور بزاوية 45 درجة لأنواع الخرائط المتوافقة، انقر على setTilt(45). ستعكس طريقة getTilt() في Map دائمًا السمة tilt الحالية التي تظهر على الخريطة، وفي حال ضبطت tilt على الخريطة، ثم أزلت لاحقًا tilt (من خلال تصغير الخريطة على سبيل المثال)، ستؤدي طريقة getTilt() على الخريطة إلى عرض 0.

ملاحظة مهمة: لا يُتاح استخدام الصور بزاوية 45 درجة إلا على الخرائط النقطية، ولا يمكن استخدامها مع الخرائط المتّجهة.

يوضّح المثال التالي عرضًا بزاوية 45 درجة لمدينة نيويورك:

TypeScript

function initMap(): void {
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      center: { lat: 40.76, lng: -73.983 },
      zoom: 15,
      mapTypeId: "satellite",
    }
  );

  map.setTilt(45);
}

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    center: { lat: 40.76, lng: -73.983 },
    zoom: 15,
    mapTypeId: "satellite",
  });

  map.setTilt(45);
}

window.initMap = initMap;
عرض مثال

تجربة عيّنة من المحتوى

الاطّلاع على مثال

تدوير الصور بزاوية 45 درجة

تتألف الصور بزاوية 45 درجة من مجموعة صور لكل اتجاه طبيعي (الشمال والجنوب الشرقي والغربي). بعد أن تعرض الخريطة صورًا بزاوية 45 درجة، يمكنك توجيه الصور إلى أحد الاتجاهات الأساسية من خلال طلب القيمة setHeading() على الكائن Map، مع ضبط قيمة عددية يتم التعبير عنها بالدرجات من الشمال.

يوضّح المثال التالي خريطة مُلتقطة من الجو ويدير الخريطة تلقائيًا كل 3 ثوانٍ عند النقر على الزر:

TypeScript

let map: google.maps.Map;

function initMap(): void {
  map = new google.maps.Map(document.getElementById("map") as HTMLElement, {
    center: { lat: 40.76, lng: -73.983 },
    zoom: 15,
    mapTypeId: "satellite",
    heading: 90,
    tilt: 45,
  });

  // add listener to button
  document.getElementById("rotate")!.addEventListener("click", autoRotate);
}

function rotate90(): void {
  const heading = map.getHeading() || 0;

  map.setHeading(heading + 90);
}

function autoRotate(): void {
  // Determine if we're showing aerial imagery.
  if (map.getTilt() !== 0) {
    window.setInterval(rotate90, 3000);
  }
}

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

let map;

function initMap() {
  map = new google.maps.Map(document.getElementById("map"), {
    center: { lat: 40.76, lng: -73.983 },
    zoom: 15,
    mapTypeId: "satellite",
    heading: 90,
    tilt: 45,
  });
  // add listener to button
  document.getElementById("rotate").addEventListener("click", autoRotate);
}

function rotate90() {
  const heading = map.getHeading() || 0;

  map.setHeading(heading + 90);
}

function autoRotate() {
  // Determine if we're showing aerial imagery.
  if (map.getTilt() !== 0) {
    window.setInterval(rotate90, 3000);
  }
}

window.initMap = initMap;
عرض مثال

تجربة عيّنة من المحتوى

الاطّلاع على مثال

تعديل سجلّ نوع الخريطة

mapTypeId في الخريطة هي معرّف سلسلة يُستخدم لربط MapType بقيمة فريدة. يحتفظ كل عنصر Map بمادة MapTypeRegistry تحتوي على مجموعة MapType المتاحة لهذه الخريطة. وتُستخدم قاعدة بيانات المسجّلين هذه لاختيار أنواع الخرائط المتوفّرة في عنصر التحكّم MapType على الخريطة.

أنك لا تقرأ مباشرةً من سجلّ نوع الخريطة. بدلاً من ذلك، يمكنك تعديل قاعدة بيانات المسجّلين عن طريق إضافة أنواع خرائط مخصّصة وربطها بمعرّف سلسلة من اختيارك. لا يمكنك تعديل أنواع الخرائط الأساسية أو تغييرها (ولكن يمكنك إزالتها من الخريطة من خلال تغيير مظهر mapTypeControlOptions المرتبط بها).

يحدِّد الرمز التالي الخريطة لعرض نوعَين من الخرائط فقط في mapTypeControlOptions وتعديل الخريطة لقاعدة بيانات المسجّلين لإضافة الربط باستخدام هذا المعرّف إلى التنفيذ الفعلي لواجهة MapType.

// Modify the control to only display two maptypes, the
// default ROADMAP and the custom 'mymap'.
// Note that because this is an association, we
// don't need to modify the MapTypeRegistry beforehand.

var MY_MAPTYPE_ID = 'mymaps';

var mapOptions = {
  zoom: 12,
  center: brooklyn,
  mapTypeControlOptions: {
     mapTypeIds: ['roadmap', MY_MAPTYPE_ID]
  },
  mapTypeId: MY_MAPTYPE_ID
};

// Create our map. This creation will implicitly create a
// map type registry.
map = new google.maps.Map(document.getElementById('map'),
    mapOptions);

// Create your custom map type using your own code.
// (See below.)
var myMapType = new MyMapType();

// Set the registry to associate 'mymap' with the
// custom map type we created, and set the map to
// show that map type.
map.mapTypes.set(MY_MAPTYPE_ID, myMapType);

خرائط ذات نمط

تسمح لك السمة StyledMapType بتخصيص طريقة عرض "خرائط Google" الأساسية العادية، وتغيير العرض المرئي لهذه العناصر مثل الطرق والمتنزّهات والمناطق السكنية لتعكس نمطًا مختلفًا عن ذلك المستخدَم في نوع الخريطة التلقائي.

للحصول على مزيد من المعلومات عن StyledMapType، يمكنك الاطّلاع على دليل الخرائط المصمَّمة على شكل أنماط.

أنواع الخرائط المخصّصة

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

هناك العديد من عمليات التنفيذ المحتملة لنوع الخريطة في واجهة برمجة تطبيقات JavaScript للخرائط:

  • مجموعات الأقسام العادية التي تتألف من صور تشكّل مجتمعة خرائط خرائط كاملة. وتُعرف مجموعات الشاشات هذه أيضًا باسم أنواع الخرائط الأساسية. تعمل أنواع الخرائط هذه وتعمل مثل أنواع الخرائط التلقائية الحالية: roadmap وsatellite وhybrid وterrain. يمكنك إضافة نوع الخريطة المخصّصة إلى مصفوفة mapTypes على الخريطة للسماح لواجهة المستخدم ضمن Maps API API للتعامل مع نوع الخريطة المخصّص كنوع خريطة عادي (من خلال تضمينها في عنصر التحكّم MapType مثلاً).
  • تراكبات الصور التي تظهر على سطح أنواع الخرائط الأساسية الحالية. بشكل عام، تُستخدم أنواع الخرائط هذه لزيادة نوع الخريطة الحالي لعرض معلومات إضافية وكثيرًا ما تكون مقتصرة على مواقع جغرافية معيّنة و/أو مستويات تكبير/تصغير. يُرجى العِلم أنّ هذه المربّعات قد تكون شفافة، ما يتيح لك إضافة ميزات إلى الخرائط الحالية.
  • أنواع الخرائط غير المصوّرة التي تسمح لك بالتلاعب بعرض معلومات الخريطة على المستوى الأساسي

يعتمد كل من هذه الخيارات على إنشاء فئة تستخدم واجهة MapType. وبالإضافة إلى ذلك، توفّر الفئة ImageMapType بعض السلوكيات المدمجة لتبسيط إنشاء أنواع خرائط الصور.

واجهة MapType

قبل إنشاء الصفوف التي تطبّق MapType، من المهم فهم الطريقة التي تحدّد بها "خرائط Google" الإحداثيات وتقرّر أجزاء الخريطة التي سيتم عرضها. عليك تنفيذ طريقة منطقية لأي نوع من أنواع الخرائط الأساسية أو المركّبة. اطّلِع على دليل إحداثيات الخريطة والمربّع.

يجب أن تنفّذ أنواع الخرائط المخصصة واجهة MapType. وتحدّد هذه الواجهة خصائص وطرقًا معيّنة تسمح لواجهة برمجة التطبيقات ببدء طلبات متعلّقة بأنواع الخرائط عندما تحتاج واجهة برمجة التطبيقات إلى عرض أقسام الخرائط ضمن إطار العرض الحالي ومستوى التكبير أو التصغير. ويمكنك التعامل مع هذه الطلبات لتحديد المربّع الذي تريد تحميله.

ملاحظة: يمكنك إنشاء صف خاص بك لتنفيذ هذه الواجهة. بدلاً من ذلك، إذا كانت لديك صور متوافقة، يمكنك استخدام فئة ImageMapType التي تنفّذ هذه الواجهة.

تتطلّب الصفوف التي تنفّذ واجهة MapType تحديد السمات التالية وتعبئتها:

  • تحدّد السمة tileSize (مطلوبة) حجم المربّع (من النوع google.maps.Size). يجب أن تكون الأحجام مستطيلة على الرغم من أنها ليست مربّعة.
  • تحدّد السمة maxZoom (مطلوبة) الحدّ الأقصى لمستوى التكبير/التصغير الذي يمكن عنده عرض مربعات هذا النوع من الخرائط.
  • تحدّد السمة minZoom (اختيارية) الحد الأدنى لمستوى التكبير/التصغير الذي يمكن عنده عرض فئة هذا النوع من الخرائط. وتكون هذه القيمة 0 تلقائيًا، ما يشير إلى عدم توفّر حد أدنى لمستوى التكبير/التصغير.
  • تحدّد السمة name (اختيارية) اسم نوع الخريطة هذا. هذه السمة ضرورية فقط إذا كنت تريد أن يكون نوع الخريطة هذا قابلاً للاختيار ضمن عنصر التحكّم في MapType. (راجِع إضافة MapType عناصر تحكّم أدناه).
  • alt (اختياري) يحدّد النص البديل لنوع الخريطة هذا الذي يظهر كنص تمرير. وهذه السمة ضرورية فقط إذا كنت تريد أن يكون نوع الخريطة هذا قابلاً للاختيار ضمن عنصر التحكّم في MapType. (راجِع إضافة MapType عنصر تحكُّم أدناه).

بالإضافة إلى ذلك، يجب تنفيذ الطرق التالية في الصفوف التي تستخدم واجهة MapType:

  • ويتم طلب getTile() (مطلوب) عندما تحدِّد واجهة برمجة التطبيقات أنّ الخريطة تحتاج إلى عرض أقسام جديدة لإطار العرض المعني. يجب أن تحتوي الطريقة getTile() على التوقيع التالي:

    getTile(tileCoord:Point,zoom:number,ownerDocument:Document):Node

    تحدّد واجهة برمجة التطبيقات ما إذا كان من الضروري طلب getTile() استنادًا إلى سمات tileSize وminZoom وmaxZoom في MapType وإطار العرض الحالي ومستوى التكبير أو التصغير في الخريطة. من المفترض أن يعرض المعالج لهذه الطريقة عنصر HTML استنادًا إلى تنسيق تم تمريره، ومستوى التكبير، وعنصر DOM الذي سيتم إلحاق صورة المربّع به.

  • يتم استدعاء releaseTile() (اختياري) عندما تحدِّد واجهة برمجة التطبيقات أنّ الخريطة تحتاج إلى إزالة مربّع عندما تصبح خارج العرض. يجب أن تحتوي هذه الطريقة على التوقيع التالي:

    releaseTile(tile:Node)

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

تُعتبر الطريقة getTile() وحدة التحكّم الرئيسية لتحديد المربّعات التي سيتم تحميلها ضمن إطار عرض معيّن.

أنواع الخرائط الأساسية

أنواع الخرائط التي تبنيها بهذه الطريقة يمكن أن تكون مستقلة أو يمكن دمجها مع أنواع خرائط أخرى على شكل عناصر مركّبة. تُعرف أنواع الخرائط المستقلة باسم أنواع الخرائط الأساسية. يمكنك استخدام واجهة برمجة التطبيقات MapType بالطريقة نفسها التي تتعامل بها مع أي نوع خريطة آخر حالي (ROADMAP، TERRAIN، إلخ). لإجراء ذلك، أضِف السمة MapType المخصّصة إلى سمة mapTypes للسمة Map. هذه السمة من النوع MapTypeRegistry.

ينشئ الرمز التالي رمز MapType أساسيًا لعرض إحداثيات مربعات الخريطة ويرسم مخططًا للمربّعات:

TypeScript

/*
 * This demo demonstrates how to replace default map tiles with custom imagery.
 * In this case, the CoordMapType displays gray tiles annotated with the tile
 * coordinates.
 *
 * Try panning and zooming the map to see how the coordinates change.
 */

class CoordMapType {
  tileSize: google.maps.Size;
  maxZoom = 19;
  name = "Tile #s";
  alt = "Tile Coordinate Map Type";

  constructor(tileSize: google.maps.Size) {
    this.tileSize = tileSize;
  }

  getTile(
    coord: google.maps.Point,
    zoom: number,
    ownerDocument: Document
  ): HTMLElement {
    const div = ownerDocument.createElement("div");

    div.innerHTML = String(coord);
    div.style.width = this.tileSize.width + "px";
    div.style.height = this.tileSize.height + "px";
    div.style.fontSize = "10";
    div.style.borderStyle = "solid";
    div.style.borderWidth = "1px";
    div.style.borderColor = "#AAAAAA";
    div.style.backgroundColor = "#E5E3DF";
    return div;
  }

  releaseTile(tile: HTMLElement): void {}
}

function initMap(): void {
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      zoom: 10,
      center: { lat: 41.85, lng: -87.65 },
      streetViewControl: false,
      mapTypeId: "coordinate",
      mapTypeControlOptions: {
        mapTypeIds: ["coordinate", "roadmap"],
        style: google.maps.MapTypeControlStyle.DROPDOWN_MENU,
      },
    }
  );

  map.addListener("maptypeid_changed", () => {
    const showStreetViewControl =
      (map.getMapTypeId() as string) !== "coordinate";

    map.setOptions({
      streetViewControl: showStreetViewControl,
    });
  });

  // Now attach the coordinate map type to the map's registry.
  map.mapTypes.set(
    "coordinate",
    new CoordMapType(new google.maps.Size(256, 256))
  );
}

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

/*
 * This demo demonstrates how to replace default map tiles with custom imagery.
 * In this case, the CoordMapType displays gray tiles annotated with the tile
 * coordinates.
 *
 * Try panning and zooming the map to see how the coordinates change.
 */
class CoordMapType {
  tileSize;
  maxZoom = 19;
  name = "Tile #s";
  alt = "Tile Coordinate Map Type";
  constructor(tileSize) {
    this.tileSize = tileSize;
  }
  getTile(coord, zoom, ownerDocument) {
    const div = ownerDocument.createElement("div");

    div.innerHTML = String(coord);
    div.style.width = this.tileSize.width + "px";
    div.style.height = this.tileSize.height + "px";
    div.style.fontSize = "10";
    div.style.borderStyle = "solid";
    div.style.borderWidth = "1px";
    div.style.borderColor = "#AAAAAA";
    div.style.backgroundColor = "#E5E3DF";
    return div;
  }
  releaseTile(tile) {}
}

function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 10,
    center: { lat: 41.85, lng: -87.65 },
    streetViewControl: false,
    mapTypeId: "coordinate",
    mapTypeControlOptions: {
      mapTypeIds: ["coordinate", "roadmap"],
      style: google.maps.MapTypeControlStyle.DROPDOWN_MENU,
    },
  });

  map.addListener("maptypeid_changed", () => {
    const showStreetViewControl = map.getMapTypeId() !== "coordinate";

    map.setOptions({
      streetViewControl: showStreetViewControl,
    });
  });
  // Now attach the coordinate map type to the map's registry.
  map.mapTypes.set(
    "coordinate",
    new CoordMapType(new google.maps.Size(256, 256)),
  );
}

window.initMap = initMap;
عرض مثال

تجربة عيّنة من المحتوى

أنواع خريطة التراكب

تم تصميم بعض أنواع الخرائط للعمل على أفضل أنواع خرائط حالية. وقد تحتوي هذه الأنواع من الخرائط على طبقات شفافة تشير إلى نقاط الاهتمام أو تعرض بيانات إضافية للمستخدم.

وفي هذه الحالات، لا تريد أن يتم التعامل مع نوع الخريطة على أنه كيان منفصل كعنصر منفصل. ويمكنك إجراء ذلك من خلال إضافة نوع الخريطة إلى MapType حالية مباشرةً باستخدام السمة overlayMapTypes على Map. يحتوي هذا الموقع على MVCArray من MapType. يتم عرض جميع أنواع الخرائط (القاعدة والتراكب) ضمن طبقة mapPane. ستُعرض أنواع خريطة التراكب في أعلى الخريطة الأساسية التي يتم إرفاقها بها، بالترتيب الذي تظهر به في مصفوفة Map.overlayMapTypes (يتم عرض التراكبات التي تحتوي على قيم فهرس أعلى أمام العناصر المركّبة ذات قيم الفهرس المنخفضة).

المثال التالي متطابق مع المثال السابق، باستثناء أنّنا أنشأنا تراكبًا للشاشة MapType فوق نوع الخريطة ROADMAP:

TypeScript

/*
 * This demo illustrates the coordinate system used to display map tiles in the
 * API.
 *
 * Tiles in Google Maps are numbered from the same origin as that for
 * pixels. For Google's implementation of the Mercator projection, the origin
 * tile is always at the northwest corner of the map, with x values increasing
 * from west to east and y values increasing from north to south.
 *
 * Try panning and zooming the map to see how the coordinates change.
 */

class CoordMapType implements google.maps.MapType {
  tileSize: google.maps.Size;
  alt: string|null = null;
  maxZoom: number = 17;
  minZoom: number = 0;
  name: string|null = null;
  projection: google.maps.Projection|null = null;
  radius: number = 6378137;

  constructor(tileSize: google.maps.Size) {
    this.tileSize = tileSize;
  }
  getTile(
    coord: google.maps.Point,
    zoom: number,
    ownerDocument: Document
  ): HTMLElement {
    const div = ownerDocument.createElement("div");

    div.innerHTML = String(coord);
    div.style.width = this.tileSize.width + "px";
    div.style.height = this.tileSize.height + "px";
    div.style.fontSize = "10";
    div.style.borderStyle = "solid";
    div.style.borderWidth = "1px";
    div.style.borderColor = "#AAAAAA";
    return div;
  }
  releaseTile(tile: Element): void {}
}

function initMap(): void {
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      zoom: 10,
      center: { lat: 41.85, lng: -87.65 },
    }
  );

  // Insert this overlay map type as the first overlay map type at
  // position 0. Note that all overlay map types appear on top of
  // their parent base map.
  const coordMapType = new CoordMapType(new google.maps.Size(256, 256))
  map.overlayMapTypes.insertAt(
    0,
    coordMapType
  );
}

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

/*
 * This demo illustrates the coordinate system used to display map tiles in the
 * API.
 *
 * Tiles in Google Maps are numbered from the same origin as that for
 * pixels. For Google's implementation of the Mercator projection, the origin
 * tile is always at the northwest corner of the map, with x values increasing
 * from west to east and y values increasing from north to south.
 *
 * Try panning and zooming the map to see how the coordinates change.
 */
class CoordMapType {
  tileSize;
  alt = null;
  maxZoom = 17;
  minZoom = 0;
  name = null;
  projection = null;
  radius = 6378137;
  constructor(tileSize) {
    this.tileSize = tileSize;
  }
  getTile(coord, zoom, ownerDocument) {
    const div = ownerDocument.createElement("div");

    div.innerHTML = String(coord);
    div.style.width = this.tileSize.width + "px";
    div.style.height = this.tileSize.height + "px";
    div.style.fontSize = "10";
    div.style.borderStyle = "solid";
    div.style.borderWidth = "1px";
    div.style.borderColor = "#AAAAAA";
    return div;
  }
  releaseTile(tile) {}
}

function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 10,
    center: { lat: 41.85, lng: -87.65 },
  });
  // Insert this overlay map type as the first overlay map type at
  // position 0. Note that all overlay map types appear on top of
  // their parent base map.
  const coordMapType = new CoordMapType(new google.maps.Size(256, 256));

  map.overlayMapTypes.insertAt(0, coordMapType);
}

window.initMap = initMap;
عرض مثال

تجربة عيّنة من المحتوى

أنواع خريطة الصور

قد يكون تنفيذ السمة MapType كنوع خريطة أساسية مهمة صعبة تستغرق وقتًا طويلاً. توفّر واجهة برمجة التطبيقات فئة خاصة تستخدم واجهة MapType لأنواع الخرائط الأكثر شيوعًا، وهي: أنواع الخرائط التي تتألف من مربّعات مكوّنة من ملفات صور واحدة.

يتم إنشاء هذه الفئة وImageMapType باستخدام مواصفات الكائن ImageMapTypeOptions التي تحدِّد السمات المطلوبة التالية:

  • تحدّد السمة tileSize (مطلوبة) حجم المربّع (من النوع google.maps.Size). يجب أن تكون الأحجام مستطيلة على الرغم من أنها ليست مربّعة.
  • تحدّد السمة getTileUrl (مطلوبة) الدالة، التي يتم توفيرها عادةً كدالة مضمّنة لدالة، للتعامل مع اختيار مربّع الصورة المناسب استنادًا إلى إحداثيات العالم ومستوى التكبير.

ينفِّذ الرمز التالي ImageMapType أساسية باستخدام مربّعات القمر من Google. يستخدم المثال دالة تسوية لضمان تكرار المربعات على طول المحور "س"، ولكن ليس على طول المحور الصادي في خريطتك.

TypeScript

function initMap(): void {
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      center: { lat: 0, lng: 0 },
      zoom: 1,
      streetViewControl: false,
      mapTypeControlOptions: {
        mapTypeIds: ["moon"],
      },
    }
  );

  const moonMapType = new google.maps.ImageMapType({
    getTileUrl: function (coord, zoom): string {
      const normalizedCoord = getNormalizedCoord(coord, zoom);

      if (!normalizedCoord) {
        return "";
      }

      const bound = Math.pow(2, zoom);
      return (
        "https://mw1.google.com/mw-planetary/lunar/lunarmaps_v1/clem_bw" +
        "/" +
        zoom +
        "/" +
        normalizedCoord.x +
        "/" +
        (bound - normalizedCoord.y - 1) +
        ".jpg"
      );
    },
    tileSize: new google.maps.Size(256, 256),
    maxZoom: 9,
    minZoom: 0,
    // @ts-ignore TODO 'radius' does not exist in type 'ImageMapTypeOptions'
    radius: 1738000,
    name: "Moon",
  });

  map.mapTypes.set("moon", moonMapType);
  map.setMapTypeId("moon");
}

// Normalizes the coords that tiles repeat across the x axis (horizontally)
// like the standard Google map tiles.
function getNormalizedCoord(coord, zoom) {
  const y = coord.y;
  let x = coord.x;

  // tile range in one direction range is dependent on zoom level
  // 0 = 1 tile, 1 = 2 tiles, 2 = 4 tiles, 3 = 8 tiles, etc
  const tileRange = 1 << zoom;

  // don't repeat across y-axis (vertically)
  if (y < 0 || y >= tileRange) {
    return null;
  }

  // repeat across x-axis
  if (x < 0 || x >= tileRange) {
    x = ((x % tileRange) + tileRange) % tileRange;
  }

  return { x: x, y: y };
}

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    center: { lat: 0, lng: 0 },
    zoom: 1,
    streetViewControl: false,
    mapTypeControlOptions: {
      mapTypeIds: ["moon"],
    },
  });
  const moonMapType = new google.maps.ImageMapType({
    getTileUrl: function (coord, zoom) {
      const normalizedCoord = getNormalizedCoord(coord, zoom);

      if (!normalizedCoord) {
        return "";
      }

      const bound = Math.pow(2, zoom);
      return (
        "https://mw1.google.com/mw-planetary/lunar/lunarmaps_v1/clem_bw" +
        "/" +
        zoom +
        "/" +
        normalizedCoord.x +
        "/" +
        (bound - normalizedCoord.y - 1) +
        ".jpg"
      );
    },
    tileSize: new google.maps.Size(256, 256),
    maxZoom: 9,
    minZoom: 0,
    // @ts-ignore TODO 'radius' does not exist in type 'ImageMapTypeOptions'
    radius: 1738000,
    name: "Moon",
  });

  map.mapTypes.set("moon", moonMapType);
  map.setMapTypeId("moon");
}

// Normalizes the coords that tiles repeat across the x axis (horizontally)
// like the standard Google map tiles.
function getNormalizedCoord(coord, zoom) {
  const y = coord.y;
  let x = coord.x;
  // tile range in one direction range is dependent on zoom level
  // 0 = 1 tile, 1 = 2 tiles, 2 = 4 tiles, 3 = 8 tiles, etc
  const tileRange = 1 << zoom;

  // don't repeat across y-axis (vertically)
  if (y < 0 || y >= tileRange) {
    return null;
  }

  // repeat across x-axis
  if (x < 0 || x >= tileRange) {
    x = ((x % tileRange) + tileRange) % tileRange;
  }
  return { x: x, y: y };
}

window.initMap = initMap;
عرض مثال

تجربة عيّنة من المحتوى

التوقعات

لكوكب الأرض هو سطح ثلاثي الأبعاد (تقريبًا)، في حين الخريطة هي سطح مسطح أبعاديًا. إنّ الخريطة التي تراها ضمن واجهة برمجة تطبيقات JavaScript للخرائط، مثل أي خريطة مسطّحة للأرض، هي عرض لهذه الكرة الأرضية على سطح مستوٍ. وبأبسطه، يمكن تعريف الإسقاط على أنه ربط لقيم خطوط العرض/الطول في إحداثيات على خريطة العرض.

يجب أن تستخدم التوقعات في واجهة برمجة تطبيقات JavaScript للخرائط واجهة Projection. يجب ألا تقدّم عملية التنفيذ Projection عملية ربط من نظام إحداثيات واحد إلى نظام آخر، بل عملية ربط ثنائية الاتجاه. وبالتالي، يجب تحديد كيفية الترجمة من إحداثيات الأرض (كائنات LatLng) إلى نظام الإحداثيات العالمية للصف Projection، والعكس صحيح. تستخدم "خرائط Google" مشروع Mercator لإنشاء خرائطها من البيانات الجغرافية وتحويل الأحداث على الخريطة إلى إحداثيات جغرافية. يمكنك الحصول على هذا العرض عن طريق الاتصال بـ getProjection() على Map (أو أي من أنواع MapType الأساسية الأساسية). وفي معظم حالات الاستخدام، يكفي هذا المعيار Projection، ولكن يمكنك أيضًا تحديد التوقعات المخصّصة واستخدامها.

تنفيذ توقعات

عند تنفيذ عرض مخصّص، عليك تحديد بعض النقاط:

  • صيغة ربط إحداثيات خطوط الطول والعرض في طائرة كاريبية والعكس صحيح (لا تتيح واجهة Projection سوى عمليات التحويل إلى إحداثيات خطية).
  • حجم المربّع الأساسي يجب أن تكون جميع الأقسام مستطيلة.
  • "حجم العالم" في الخريطة باستخدام القسم الأساسي الذي تم ضبطه على مستوى التكبير أو التصغير 0 لاحِظ أنّه بالنسبة إلى الخرائط التي تتألف من جزء واحد عند التكبير أو التصغير، يكون حجم العالم وحجم المربّع الأساسي متطابقَين.

تنسيق عمليات التحويل في التوقعات

يوفّر كل توقع طريقتَين للترجمة بين هذين النظامَين، ما يتيح لك التبديل بين الإحداثيات الجغرافية والعالمية:

  • تحوّل الطريقة Projection.fromLatLngToPoint() قيمة LatLng إلى صيغة عالمية. تُستخدم هذه الطريقة لوضع التراكبات على الخريطة (ولوضع الخريطة نفسها).
  • تحوِّل الطريقة Projection.fromPointToLatLng() إحداثيات عالمية إلى قيمة LatLng. تُستخدم هذه الطريقة لتحويل الأحداث مثل النقرات التي تتم على الخريطة إلى إحداثيات جغرافية.

تفترض "خرائط Google" أن الإسقاطات خطية.

بشكل عام، يمكنك استخدام العرض لحالتين: لإنشاء خريطة للعالم أو لإنشاء خريطة لمنطقة محلية. في الحالة السابقة، عليك التأكّد من أنّ توقعاتك أيضًا مستطيلة وطبيعية على جميع خطوط الطول. قد تكون بعض التوقعات (خصوصًا التوقعات ذات شكل مخروطي) "عادية" (أي من خلال الشمال) ولكنها تنحرف عن الشمال، على سبيل المثال، كلما تم تحديد موضع الخريطة بالنسبة إلى بعض خطوط الطول المرجعية. يمكنك استخدام هذا العرض على المستوى المحلي، ولكن يُرجى العِلم أنّ التوقعات لا تكون بالضرورة دقيقة، إذ ستلاحظ أنّ الأخطاء في عملية التحويل قد تظهر بشكل أبعد عن خط الطول المرجعي الذي تنحرف عنه.

اختيار مربّع الخريطة في التوقعات

لا تكون التوقعات مفيدة فقط لتحديد مواضع المواقع الجغرافية أو العناصر المركّبة، ولكن أيضًا لتحديد مواضع مربعات الخرائط. تعرض واجهة برمجة تطبيقات JavaScript للخرائط الخرائط الأساسية باستخدام واجهة MapType، والتي يجب أن تشير إلى كل من السمة projection لتحديد إسقاط الخريطة وطريقة getTile() لاسترداد مربعات الخريطة استنادًا إلى قيم تنسيق الأقسام. تستند إحداثيات المربّعات إلى الحجم الأساسي للمربّع (الذي يجب أن يكون مستطيلاً) و "الحجم العالمي" لخريطةك، وهو حجم البكسل لعالم الخريطة على مستوى التكبير 0. (بالنسبة إلى الخرائط التي تتألف من مربّع واحد عند التكبير أو التصغير، يكون حجم المربّع وحجم العالم متطابقَين).

يمكنك تحديد حجم المربّع الأساسي ضمن سمة tileSize الخاصة بـ MapType. أنت تحدّد حجم العالم بشكل ضمني ضمن طريقتَي العرض fromLatLngToPoint() وfromPointToLatLng().

بما أنّ اختيار الصور يعتمد على هذه القيم التي تم تمريرها، من المفيد تسمية الصور التي يمكن اختيارها آليًا وفقًا لتلك القيم التي تم تمريرها، مثل map_zoom_tileX_tileY.png.

يحدّد المثال التالي تعريف ImageMapType باستخدام عرض Gall-Peters:

TypeScript

// This example defines an image map type using the Gall-Peters
// projection.
// https://en.wikipedia.org/wiki/Gall%E2%80%93Peters_projection

function initMap(): void {
  // Create a map. Use the Gall-Peters map type.
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      zoom: 0,
      center: { lat: 0, lng: 0 },
      mapTypeControl: false,
    }
  );

  initGallPeters();
  map.mapTypes.set("gallPeters", gallPetersMapType);
  map.setMapTypeId("gallPeters");

  // Show the lat and lng under the mouse cursor.
  const coordsDiv = document.getElementById("coords") as HTMLElement;

  map.controls[google.maps.ControlPosition.TOP_CENTER].push(coordsDiv);
  map.addListener("mousemove", (event: google.maps.MapMouseEvent) => {
    coordsDiv.textContent =
      "lat: " +
      Math.round(event.latLng!.lat()) +
      ", " +
      "lng: " +
      Math.round(event.latLng!.lng());
  });

  // Add some markers to the map.
  map.data.setStyle((feature) => {
    return {
      title: feature.getProperty("name"),
      optimized: false,
    };
  });
  map.data.addGeoJson(cities);
}

let gallPetersMapType;

function initGallPeters() {
  const GALL_PETERS_RANGE_X = 800;
  const GALL_PETERS_RANGE_Y = 512;

  // Fetch Gall-Peters tiles stored locally on our server.
  gallPetersMapType = new google.maps.ImageMapType({
    getTileUrl: function (coord, zoom) {
      const scale = 1 << zoom;

      // Wrap tiles horizontally.
      const x = ((coord.x % scale) + scale) % scale;

      // Don't wrap tiles vertically.
      const y = coord.y;

      if (y < 0 || y >= scale) return "";

      return (
        "https://developers.google.com/maps/documentation/" +
        "javascript/examples/full/images/gall-peters_" +
        zoom +
        "_" +
        x +
        "_" +
        y +
        ".png"
      );
    },
    tileSize: new google.maps.Size(GALL_PETERS_RANGE_X, GALL_PETERS_RANGE_Y),
    minZoom: 0,
    maxZoom: 1,
    name: "Gall-Peters",
  });

  // Describe the Gall-Peters projection used by these tiles.
  gallPetersMapType.projection = {
    fromLatLngToPoint: function (latLng) {
      const latRadians = (latLng.lat() * Math.PI) / 180;
      return new google.maps.Point(
        GALL_PETERS_RANGE_X * (0.5 + latLng.lng() / 360),
        GALL_PETERS_RANGE_Y * (0.5 - 0.5 * Math.sin(latRadians))
      );
    },
    fromPointToLatLng: function (point, noWrap) {
      const x = point.x / GALL_PETERS_RANGE_X;
      const y = Math.max(0, Math.min(1, point.y / GALL_PETERS_RANGE_Y));

      return new google.maps.LatLng(
        (Math.asin(1 - 2 * y) * 180) / Math.PI,
        -180 + 360 * x,
        noWrap
      );
    },
  };
}

// GeoJSON, describing the locations and names of some cities.
const cities = {
  type: "FeatureCollection",
  features: [
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [-87.65, 41.85] },
      properties: { name: "Chicago" },
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [-149.9, 61.218] },
      properties: { name: "Anchorage" },
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [-99.127, 19.427] },
      properties: { name: "Mexico City" },
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [-0.126, 51.5] },
      properties: { name: "London" },
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [28.045, -26.201] },
      properties: { name: "Johannesburg" },
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [15.322, -4.325] },
      properties: { name: "Kinshasa" },
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [151.207, -33.867] },
      properties: { name: "Sydney" },
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [0, 0] },
      properties: { name: "0°N 0°E" },
    },
  ],
};

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

// This example defines an image map type using the Gall-Peters
// projection.
// https://en.wikipedia.org/wiki/Gall%E2%80%93Peters_projection
function initMap() {
  // Create a map. Use the Gall-Peters map type.
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 0,
    center: { lat: 0, lng: 0 },
    mapTypeControl: false,
  });

  initGallPeters();
  map.mapTypes.set("gallPeters", gallPetersMapType);
  map.setMapTypeId("gallPeters");

  // Show the lat and lng under the mouse cursor.
  const coordsDiv = document.getElementById("coords");

  map.controls[google.maps.ControlPosition.TOP_CENTER].push(coordsDiv);
  map.addListener("mousemove", (event) => {
    coordsDiv.textContent =
      "lat: " +
      Math.round(event.latLng.lat()) +
      ", " +
      "lng: " +
      Math.round(event.latLng.lng());
  });
  // Add some markers to the map.
  map.data.setStyle((feature) => {
    return {
      title: feature.getProperty("name"),
      optimized: false,
    };
  });
  map.data.addGeoJson(cities);
}

let gallPetersMapType;

function initGallPeters() {
  const GALL_PETERS_RANGE_X = 800;
  const GALL_PETERS_RANGE_Y = 512;

  // Fetch Gall-Peters tiles stored locally on our server.
  gallPetersMapType = new google.maps.ImageMapType({
    getTileUrl: function (coord, zoom) {
      const scale = 1 << zoom;
      // Wrap tiles horizontally.
      const x = ((coord.x % scale) + scale) % scale;
      // Don't wrap tiles vertically.
      const y = coord.y;

      if (y < 0 || y >= scale) return "";
      return (
        "https://developers.google.com/maps/documentation/" +
        "javascript/examples/full/images/gall-peters_" +
        zoom +
        "_" +
        x +
        "_" +
        y +
        ".png"
      );
    },
    tileSize: new google.maps.Size(GALL_PETERS_RANGE_X, GALL_PETERS_RANGE_Y),
    minZoom: 0,
    maxZoom: 1,
    name: "Gall-Peters",
  });
  // Describe the Gall-Peters projection used by these tiles.
  gallPetersMapType.projection = {
    fromLatLngToPoint: function (latLng) {
      const latRadians = (latLng.lat() * Math.PI) / 180;
      return new google.maps.Point(
        GALL_PETERS_RANGE_X * (0.5 + latLng.lng() / 360),
        GALL_PETERS_RANGE_Y * (0.5 - 0.5 * Math.sin(latRadians)),
      );
    },
    fromPointToLatLng: function (point, noWrap) {
      const x = point.x / GALL_PETERS_RANGE_X;
      const y = Math.max(0, Math.min(1, point.y / GALL_PETERS_RANGE_Y));
      return new google.maps.LatLng(
        (Math.asin(1 - 2 * y) * 180) / Math.PI,
        -180 + 360 * x,
        noWrap,
      );
    },
  };
}

// GeoJSON, describing the locations and names of some cities.
const cities = {
  type: "FeatureCollection",
  features: [
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [-87.65, 41.85] },
      properties: { name: "Chicago" },
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [-149.9, 61.218] },
      properties: { name: "Anchorage" },
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [-99.127, 19.427] },
      properties: { name: "Mexico City" },
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [-0.126, 51.5] },
      properties: { name: "London" },
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [28.045, -26.201] },
      properties: { name: "Johannesburg" },
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [15.322, -4.325] },
      properties: { name: "Kinshasa" },
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [151.207, -33.867] },
      properties: { name: "Sydney" },
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [0, 0] },
      properties: { name: "0°N 0°E" },
    },
  ],
};

window.initMap = initMap;
عرض مثال

تجربة عيّنة من المحتوى