انواع نقشه

پلتفرم را انتخاب کنید: Android iOS JavaScript

این سند انواع نقشه هایی را که می توانید با استفاده از Maps JavaScript API نمایش دهید، مورد بحث قرار می دهد. API از یک شی MapType برای نگهداری اطلاعات در مورد این نقشه ها استفاده می کند. MapType رابطی است که نمایش و استفاده از کاشی های نقشه و ترجمه سیستم های مختصات را از مختصات صفحه به مختصات جهانی (روی نقشه) تعریف می کند. هر MapType باید شامل چند روش برای رسیدگی به بازیابی و رهاسازی کاشی ها و ویژگی هایی باشد که رفتار بصری آن را مشخص می کند.

عملکرد داخلی انواع نقشه در Maps JavaScript API یک موضوع پیشرفته است. اکثر توسعه دهندگان می توانند از انواع نقشه های اصلی که در زیر ذکر شده است استفاده کنند. با این حال، همچنین می‌توانید ارائه انواع نقشه‌های موجود را با استفاده از Styled Maps تغییر دهید یا کاشی‌های نقشه خود را با استفاده از انواع نقشه سفارشی تعریف کنید. هنگام ارائه انواع نقشه های سفارشی، باید بدانید که چگونه رجیستری نوع نقشه نقشه را تغییر دهید.

انواع نقشه های اساسی

چهار نوع نقشه در Maps JavaScript API موجود است. علاوه بر کاشی های آشنای نقشه راه "نقاشی شده"، Maps JavaScript 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 با استفاده از یک شناسه تنظیم می کنید. Maps JavaScript API از یک رجیستری نوع نقشه، که در زیر توضیح داده شده است، برای مدیریت این مراجع استفاده می کند.

تصویر 45 درجه

Maps JavaScript API از تصاویر 45 درجه ویژه برای مکان‌های خاص پشتیبانی می‌کند. این تصاویر با وضوح بالا نماهای پرسپکتیو را به سمت هر یک از جهت های اصلی (شمال، جنوب، شرق، غرب) ارائه می دهد. این تصاویر در سطوح بزرگنمایی بالاتر برای انواع نقشه های پشتیبانی شده در دسترس هستند.

تصویر زیر نمای 45 درجه ای از شهر نیویورک را نشان می دهد:

انواع نقشه های satellite و hybrid از تصاویر 45 درجه در سطوح زوم بالا (12 و بیشتر) در صورت وجود پشتیبانی می کنند. اگر کاربر در مکانی بزرگنمایی کند که چنین تصاویری برای آن وجود دارد، این نوع نقشه ها به طور خودکار نماهای خود را به روش زیر تغییر می دهند:

  • تصاویر ماهواره‌ای یا ترکیبی با تصاویری جایگزین می‌شوند که پرسپکتیو 45 درجه را با مرکز مکان فعلی ارائه می‌دهند. به طور پیش فرض، چنین نماهایی به سمت شمال جهت گیری می شوند. اگر کاربر کوچک‌نمایی کند، تصاویر ماهواره‌ای یا ترکیبی پیش‌فرض دوباره ظاهر می‌شوند. این رفتار بسته به سطح زوم و مقدار tilt متفاوت است:
    • بین سطوح زوم 12 و 18، نقشه پایه از بالا به پایین (0 درجه) به طور پیش فرض نمایش داده می شود مگر اینکه tilt 45 تنظیم شده باشد.
    • در سطوح زوم 18 یا بیشتر، نقشه پایه 45 درجه نمایش داده می شود مگر اینکه tilt روی 0 تنظیم شده باشد.
  • کنترل چرخش قابل مشاهده می شود. کنترل چرخش گزینه هایی را ارائه می دهد که کاربر را قادر می سازد شیب را تغییر دهد و نما را با افزایش 90 درجه در هر جهت بچرخاند. برای پنهان کردن کنترل چرخش، rotateControl روی false قرار دهید.

بزرگنمایی از یک نوع نقشه که تصاویر 45 درجه را نشان می دهد، هر یک از این تغییرات را برمی گرداند و انواع نقشه اصلی را دوباره ایجاد می کند.

تصویر 45 درجه را فعال و غیرفعال کنید

می توانید با فراخوانی setTilt(0) روی شی Map ، تصویر 45 درجه را غیرفعال کنید. برای فعال کردن تصاویر 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;

جاوا اسکریپت

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;
مشاهده نمونه

Sample را امتحان کنید

مشاهده نمونه

چرخش 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;

جاوا اسکریپت

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;
مشاهده نمونه

Sample را امتحان کنید

مشاهده نمونه

رجیستری نوع نقشه را تغییر دهید

mapTypeId نقشه یک شناسه رشته ای است که برای مرتبط کردن MapType با یک مقدار منحصر به فرد استفاده می شود. هر شی Map یک MapTypeRegistry دارد که شامل مجموعه MapType های موجود برای آن نقشه است. از این رجیستری برای انتخاب انواع نقشه هایی که در کنترل MapType Maps موجود هستند، استفاده می شود.

شما مستقیماً از رجیستری نوع نقشه نمی خوانید. در عوض، رجیستری را با اضافه کردن انواع نقشه های سفارشی و مرتبط کردن آنها با یک شناسه رشته دلخواه تغییر می دهید. شما نمی توانید انواع اصلی نقشه را تغییر دهید یا تغییر دهید (البته می توانید با تغییر ظاهر نقشه 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 ، به استفاده از اعلان‌های سبک JSON تعبیه‌شده مراجعه کنید.

انواع نقشه سفارشی

Maps JavaScript API از نمایش و مدیریت انواع نقشه‌های سفارشی پشتیبانی می‌کند و به شما امکان می‌دهد تصاویر نقشه یا پوشش‌های کاشی خود را پیاده‌سازی کنید.

چندین پیاده سازی ممکن از نوع نقشه در Maps JavaScript API وجود دارد:

  • مجموعه‌های کاشی استاندارد متشکل از تصاویری که در مجموع نقشه‌های کامل نقشه‌کشی را تشکیل می‌دهند. این مجموعه کاشی ها به عنوان انواع نقشه های پایه نیز شناخته می شوند. این انواع نقشه مانند انواع نقشه های پیش فرض موجود عمل می کنند و رفتار می کنند: roadmap ، satellite ، hybrid و terrain . می توانید نوع نقشه سفارشی خود را به آرایه mapTypes Map اضافه کنید تا به رابط کاربری در Maps JavaScript API اجازه دهید تا نوع نقشه سفارشی شما را به عنوان یک نوع نقشه استاندارد در نظر بگیرد (مثلاً با قرار دادن آن در کنترل MapType).
  • پوشش‌های کاشی تصویری که در بالای انواع نقشه پایه موجود نمایش داده می‌شوند. به طور کلی، این انواع نقشه برای تقویت یک نوع نقشه موجود برای نمایش اطلاعات اضافی استفاده می شود و اغلب به مکان های خاص و/یا سطوح زوم محدود می شود. توجه داشته باشید که این کاشی‌ها ممکن است شفاف باشند و به شما امکان می‌دهند ویژگی‌هایی را به نقشه‌های موجود اضافه کنید.
  • انواع نقشه های غیر تصویری، که به شما امکان می دهد نمایش اطلاعات نقشه را در اساسی ترین سطح آن دستکاری کنید.

هر یک از این گزینه ها متکی به ایجاد کلاسی است که رابط MapType را پیاده سازی می کند. علاوه بر این، کلاس ImageMapType برخی رفتارهای داخلی را برای ساده سازی ایجاد انواع نقشه های تصویری ارائه می دهد.

رابط MapType

قبل از ایجاد کلاس‌هایی که MapType پیاده‌سازی می‌کنند، مهم است که بدانید Google Maps چگونه مختصات را تعیین می‌کند و تصمیم می‌گیرد کدام قسمت‌های نقشه را نشان دهد. شما باید منطق مشابهی را برای هر نوع نقشه پایه یا پوششی پیاده سازی کنید. راهنمای مختصات نقشه و کاشی را بخوانید.

انواع نقشه های سفارشی باید رابط MapType را پیاده سازی کنند. این رابط ویژگی‌ها و روش‌های خاصی را مشخص می‌کند که به API اجازه می‌دهد زمانی که API تشخیص می‌دهد که باید کاشی‌های نقشه را در نمای فعلی و سطح زوم نمایش دهد، درخواست‌هایی را برای نوع(های) نقشه شما آغاز کند. شما با این درخواست ها تصمیم می گیرید کدام کاشی را بارگیری کنید.

توجه : می توانید کلاس خود را برای پیاده سازی این رابط ایجاد کنید. از طرف دیگر، اگر تصاویر سازگار دارید، می توانید از کلاس ImageMapType استفاده کنید که قبلاً این رابط را پیاده سازی می کند.

کلاس هایی که رابط MapType را پیاده سازی می کنند نیاز دارند که ویژگی های زیر را تعریف و پر کنید:

  • tileSize (الزامی) اندازه کاشی (از نوع google.maps.Size ) را مشخص می کند. اندازه ها باید مستطیل شکل باشند، اگرچه نیازی به مربع ندارند.
  • maxZoom (الزامی) حداکثر سطح بزرگنمایی را برای نمایش کاشی های این نوع نقشه مشخص می کند.
  • minZoom (اختیاری) حداقل سطح بزرگنمایی را برای نمایش کاشی از این نوع نقشه مشخص می کند. به طور پیش فرض، این مقدار 0 است که نشان می دهد حداقل سطح بزرگنمایی وجود ندارد.
  • name (اختیاری) نام این نوع نقشه را مشخص می کند. این ویژگی فقط در صورتی ضروری است که بخواهید این نوع نقشه در یک کنترل MapType قابل انتخاب باشد. ( گزینه های کنترل را ببینید.)
  • alt (اختیاری) متن جایگزین را برای این نوع نقشه مشخص می کند که به عنوان متن شناور نمایش داده می شود. این ویژگی فقط در صورتی ضروری است که بخواهید این نوع نقشه در یک کنترل MapType قابل انتخاب باشد. ( گزینه های کنترل را ببینید.)

علاوه بر این، کلاس هایی که رابط MapType را پیاده سازی می کنند، باید متدهای زیر را پیاده سازی کنند:

  • getTile() (الزامی) زمانی فراخوانی می شود که API تشخیص دهد که نقشه نیاز به نمایش کاشی های جدید برای نمای داده شده دارد. متد getTile() باید دارای امضای زیر باشد:

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

    API تعیین می کند که آیا نیاز به فراخوانی getTile() بر اساس ویژگی های tileSize ، minZoom ، و maxZoom MapType و نمای فعلی نقشه و سطح زوم است. کنترل‌کننده این روش باید یک عنصر HTML را با توجه به مختصات، سطح بزرگ‌نمایی و عنصر DOM برگرداند تا تصویر کاشی را به آن اضافه کند.

  • releaseTile() (اختیاری) زمانی فراخوانی می شود که API تشخیص دهد که نقشه باید یک کاشی را حذف کند زیرا از دید خارج می شود. این روش باید دارای امضای زیر باشد:

    releaseTile(tile:Node)

    شما معمولاً باید پس از اضافه شدن به نقشه، تمام عناصری را که به کاشی های نقشه متصل شده اند حذف کنید. برای مثال، اگر شنونده‌های رویداد را به همپوشانی‌های کاشی نقشه پیوست کرده‌اید، باید آنها را از اینجا حذف کنید.

متد getTile() به عنوان کنترل‌کننده اصلی برای تعیین اینکه کدام کاشی‌ها در یک Viewport بارگذاری شوند، عمل می‌کند.

انواع نقشه پایه

انواع نقشه‌هایی که به این روش می‌سازید ممکن است به تنهایی یا با دیگر انواع نقشه‌ها به عنوان همپوشانی ترکیب شوند. انواع نقشه های مستقل به عنوان انواع نقشه پایه شناخته می شوند. ممکن است بخواهید که API با 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;

جاوا اسکریپت

/*
 * 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;
مشاهده نمونه

Sample را امتحان کنید

انواع نقشه روکش

برخی از انواع نقشه برای کار بر روی انواع نقشه های موجود طراحی شده اند. این گونه نقشه ها ممکن است لایه های شفافی داشته باشند که نقاط مورد علاقه را نشان می دهد یا داده های اضافی را به کاربر نشان می دهد.

در این موارد، شما نمی خواهید که نوع نقشه به عنوان یک موجودیت جداگانه در نظر گرفته شود، بلکه به عنوان یک پوشش. می توانید این کار را با افزودن نوع نقشه به MapType موجود مستقیماً با استفاده از ویژگی overlayMapTypes Map انجام دهید. این ویژگی حاوی یک MVCArray از MapType s است. همه انواع نقشه (پایه و روکش) در لایه 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;

جاوا اسکریپت

/*
 * 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;
مشاهده نمونه

Sample را امتحان کنید

انواع نقشه های تصویری

پیاده سازی MapType برای عمل به عنوان یک نوع نقشه پایه می تواند یک کار وقت گیر و پر زحمت باشد. API کلاس خاصی را ارائه می‌کند که رابط MapType برای رایج‌ترین انواع نقشه پیاده‌سازی می‌کند: انواع نقشه که از کاشی‌هایی تشکیل شده از فایل‌های تصویری منفرد تشکیل شده‌اند.

این کلاس، کلاس ImageMapType ، با استفاده از مشخصات شی ImageMapTypeOptions که ویژگی های مورد نیاز زیر را تعریف می کند، ساخته می شود:

  • tileSize (الزامی) اندازه کاشی (از نوع google.maps.Size ) را مشخص می کند. اندازه ها باید مستطیل شکل باشند، اگرچه نیازی به مربع ندارند.
  • getTileUrl (الزامی) تابعی را مشخص می‌کند که معمولاً به‌عنوان یک تابع درون خطی به صورت تحت اللفظی ارائه می‌شود، تا انتخاب کاشی تصویر مناسب را بر اساس مختصات جهان ارائه‌شده و سطح بزرگ‌نمایی انجام دهد.

کد زیر یک ImageMapType اولیه را با استفاده از کاشی های ماه گوگل پیاده سازی می کند. این مثال از یک تابع عادی سازی استفاده می کند تا اطمینان حاصل شود که کاشی ها در امتداد محور x تکرار می شوند، اما نه در امتداد محور y نقشه شما.

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;

جاوا اسکریپت

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;
مشاهده نمونه

Sample را امتحان کنید

پیش بینی ها

زمین یک کره سه بعدی (تقریبا) است، در حالی که نقشه یک سطح دو بعدی صاف است. نقشه ای که در Maps JavaScript API مشاهده می کنید، مانند هر نقشه مسطحی از زمین، نمایش آن کره بر روی یک سطح صاف است. در ساده ترین عبارت، یک طرح ریزی را می توان به عنوان نگاشت مقادیر طول و عرض جغرافیایی به مختصات روی نقشه طرح ریزی تعریف کرد.

پیش‌بینی‌ها در Maps JavaScript API باید رابط Projection را پیاده‌سازی کنند. یک پیاده سازی Projection باید نه تنها یک نقشه برداری از یک سیستم مختصات به سیستم دیگر، بلکه یک نقشه برداری دو طرفه را نیز ارائه دهد. یعنی باید نحوه ترجمه از مختصات زمین (اشیاء LatLng ) به سیستم مختصات جهانی کلاس Projection و از سیستم مختصات جهان به مختصات زمین را تعریف کنید. Google Maps از طرح Mercator برای ایجاد نقشه های خود از داده های جغرافیایی و تبدیل رویدادهای روی نقشه به مختصات جغرافیایی استفاده می کند. شما می توانید با فراخوانی getProjection() روی Map (یا هر نوع از انواع MapType پایه استاندارد) این Projection را بدست آورید.

اجرای یک پروجکشن

هنگام اجرای یک طرح سفارشی، باید چند چیز را تعریف کنید:

  • فرمول های نگاشت مختصات طول و عرض جغرافیایی به یک صفحه دکارتی و فرمول های مربوطه برای نگاشت از صفحه دکارتی به مختصات طول و عرض جغرافیایی. (رابط Projection فقط از تبدیل به مختصات مستطیلی پشتیبانی می کند.)
  • اندازه کاشی پایه تمام کاشی ها باید مستطیل شکل باشند.
  • "اندازه جهانی" نقشه با استفاده از کاشی پایه در سطح زوم 0 تنظیم شده است. توجه داشته باشید که برای نقشه هایی که از یک کاشی با بزرگنمایی 0 تشکیل شده اند، اندازه جهانی و اندازه کاشی پایه یکسان است.

هماهنگی تحولات در پیش بینی ها

هر طرح دو روش را ارائه می دهد که بین این دو سیستم مختصات ترجمه می شود و به شما امکان می دهد بین مختصات جغرافیایی و جهانی تبدیل کنید:

  • متد Projection.fromLatLngToPoint() یک مقدار LatLng به یک مختصات جهانی تبدیل می کند. این روش برای قرار دادن همپوشانی ها روی نقشه (و موقعیت خود نقشه) استفاده می شود.
  • متد Projection.fromPointToLatLng() یک مختصات جهانی را به مقدار LatLng تبدیل می کند. این روش برای تبدیل رویدادهایی مانند کلیک هایی که روی نقشه اتفاق می افتد به مختصات جغرافیایی استفاده می شود.

نقشه های گوگل فرض می کند که پیش بینی ها مستطیل هستند.

به طور کلی، شما ممکن است از یک طرح برای دو مورد استفاده کنید: برای ایجاد یک نقشه از جهان، یا برای ایجاد یک نقشه از یک منطقه محلی. در حالت اول، باید اطمینان حاصل کنید که طرح شما در تمام طول‌های جغرافیایی مستطیل و نرمال است. برخی از برجستگی ها (به ویژه برآمدگی های مخروطی) ممکن است "به صورت محلی عادی" باشند (یعنی نقطه شمال) اما از شمال واقعی منحرف شوند. برای مثال، هر چه نقشه نسبت به طول جغرافیایی مرجع بیشتر قرار گیرد. شما ممکن است از چنین طرح ریزی به صورت محلی استفاده کنید، اما توجه داشته باشید که طرح ریزی لزوماً نادقیق است و خطاهای تبدیل ظاهراً هر چه از طول جغرافیایی مرجع منحرف می شوید بیشتر می شود.

انتخاب کاشی نقشه در پیش بینی ها

پیش بینی ها نه تنها برای تعیین موقعیت مکان ها یا پوشش ها، بلکه برای تعیین موقعیت خود کاشی های نقشه مفید هستند. Maps JavaScript API نقشه‌های پایه را با استفاده از رابط MapType ارائه می‌کند، که باید هم یک ویژگی projection برای شناسایی طرح‌ریزی نقشه و هم یک متد getTile() برای بازیابی کاشی‌های نقشه بر اساس مقادیر مختصات کاشی اعلام کند. مختصات کاشی بر اساس اندازه اصلی کاشی شما (که باید مستطیل شکل باشد) و "اندازه جهانی" نقشه شما است که اندازه پیکسل جهان نقشه شما در سطح زوم 0 است. (برای نقشه هایی که از یک کاشی با بزرگنمایی 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") as string,
      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;

جاوا اسکریپت

// 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;
مشاهده نمونه

Sample را امتحان کنید