JavaScript في 60 ثانية: العمل مع خريطة (Geolocation API، Leaflet.js، Nominatim)





يوم جيد ، أيها الأصدقاء!



في هذا البرنامج التعليمي الصغير ، سنكمل ثلاث مهام بسيطة معك:



  • باستخدام واجهة برمجة تطبيقات تحديد الموقع الجغرافي و Leaflet.js ، حدد موقع المستخدم الحالي واعرضه على الخريطة
  • نقوم بتنفيذ انتقال متحرك بين المدن
  • نقوم بالتبديل بين العناوين مع الحصول المبدئي على اسم الكائن وإحداثياته


كود المشروع هنا .



يمكنك اللعب بالرمز هنا:







تحديد الموقع الحالي للمستخدم



تسمح واجهة برمجة تطبيقات تحديد الموقع الجغرافي للمستخدم بتزويد تطبيق ويب ببيانات الموقع الخاصة به. يستخدم التطبيق طريقة Geolocation.getCurrentPosition () لطلب هذه البيانات . تتطلب هذه الطريقة معلمة واحدة مطلوبة ومعلمتين اختياريتين: النجاح هو وظيفة رد اتصال تتلقى كائن الموضع عند منح الإذن ، والخطأ هو وظيفة رد اتصال تتلقى كائن PositionError عند رفض الوصول ، والخيارات هي كائن إعدادات. هكذا تبدو في الكود:



navigator.geolocation.getCurrentPosition(success, error, {
  //  
  enableHighAccuracy: true
})

function success({ coords }) {
  //    
  const { latitude, longitude } = coords
  const position = [latitude, longitude]
  console.log(position) // [, ]
}

function error({ message }) {
  console.log(message) //      PositionError: User denied Geolocation
}

      
      





عرض موقع المستخدم على الخريطة



سوف نستخدم Leaflet.js كخريطة . هذه الخدمة هي بديل لخرائط Google و OpenStreetMap ، وهي أدنى منها في الوظائف ، لكنها جذابة مع بساطة الواجهة. نقوم بإنشاء ترميز نربط فيه الأنماط ونص الخريطة:



<head>
  <!--   -->
  <link
      rel="stylesheet"
      href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
      integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
      crossorigin=""
    />
    <!--   -->
    <script
      src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
      integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
      crossorigin=""
    ></script>
    <!--   -->
    <link rel="stylesheet" href="style.css" />
</head>
<body>
  <!--    -->
  <div id="map"></div>
  <!--     -->
  <button id="my_position">My Position</button>
  <!--  - -->
  <script src="script.js" type="module"></script>
</body>

      
      





أضف الحد الأدنى من الأنماط (style.css):



* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  min-height: 100vh;
  display: grid;
  place-content: center;
  place-items: center;
  background-color: rgb(241, 241, 241);
}

#map {
  width: 480px;
  height: 320px;
  border-radius: 4px;
  box-shadow: 0 0 1px #222;
}

button {
  padding: 0.25em 0.75em;
  margin: 1em 0.5em;
  cursor: pointer;
  user-select: none;
}

      
      





قم بإنشاء وحدة map.js بالمحتوى التالي:



//       
//      
let map = null
let marker = null

//    -     
//  ,    (tooltip)
export function getMap(position, tooltip) {
  //     
  if (map === null) {
    //  ,   setView -   (zoom)
    map = L.map('map').setView(position, 15)
  } else return

  // -  
  //      
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution:
      '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
  }).addTo(map)

  //    
  L.marker(position).addTo(map).bindPopup(tooltip).openPopup()
}

      
      





أخيرًا ، قمنا بإنشاء script.js:



//  
import { getMap } from './map.js'

//       
document.getElementById('my_position').onclick = () => {
  navigator.geolocation.getCurrentPosition(success, error, {
    enableHighAccuracy: true
  })
}

function success({ coords }) {
  const { latitude, longitude } = coords
  const currentPosition = [latitude, longitude]
  //  ,      
  getMap(currentPosition, 'You are here')
}

function error({ message }) {
  console.log(message)
}

      
      





افتح index.html في المتصفح ، وانقر على الزر ، وامنح الإذن لتلقي بيانات الموقع ، واطلع على موقعنا على الخريطة.







غرامة. المضي قدما.



الانتقال المتحرك بين المدن



لنفترض أن لدينا كائنًا به ثلاث مدن (موسكو ، وسانت بطرسبرغ ، وإيكاترينبرج) وإحداثياتها (db / Cities.json):



{
  "Moscow": {
    "lat": "55.7522200",
    "lon": "37.6155600"
  },
  "Saint-Petersburg": {
    "lat": "59.9386300",
    "lon": "30.3141300"
  },
  "Ekaterinburg": {
    "lat": "56.8519000",
    "lon": "60.6122000"
  }
}

      
      





نحن بحاجة إلى تنفيذ التبديل السلس بين هذه المدن على الخريطة.



أضف حاوية للمدن إلى الترميز:



<div id="cities"></div>

      
      





إعادة كتابة script.js:



import { getMap } from './map.js'

//    
const $cities = document.getElementById('cities')

;(async () => {
  //    
  const response = await fetch('./db/cities.json')
  const cities = await response.json()
  //  
  for (const city in cities) {
    //  
    const $button = document.createElement('button')

    //    -  
    $button.textContent = city

    //    
    const { lat, lon } = cities[city]

    //   ,   
    //   data-
    $button.dataset.city = city
    $button.dataset.lat = lat
    $button.dataset.lon = lon

    //    
    $cities.append($button)
  }
})()

//   
$cities.addEventListener('click', ({ target }) => {
  //     
  if (target.tagName !== 'BUTTON') return

  //   ,     data-
  const { city, lat, lon } = target.dataset
  const position = [lat, lon]
  //  ,      
  getMap(position, city)
})

      
      





دعونا أيضًا نغير map.js قليلاً:



let map = null
let marker = null

export function getMap(position, tooltip) {
  if (map === null) {
    map = L.map('map').setView(position, 15)
  } else {
    //    
    map.flyTo(position)
  }

  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution:
      '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
  }).addTo(map)

  //   
  if (marker) {
    map.removeLayer(marker)
  }
  marker = new L.Marker(position).addTo(map).bindPopup(tooltip).openPopup()
}

      
      





افتح index.html. عندما تضغط على الزر الأول ، نحصل على الفور على موقع واسم المدينة. عندما تضغط على الزر الثاني والأزرار اللاحقة ، فإننا نتنقل بسلاسة بين المدن.







سهولة التبديل بين العناوين



لنفترض أن لدينا ثلاثة كائنات بأسماء وعناوين (db / address.json):



{
  " ": " , 2",
  "   ": " , 46",
  "-": " , 97"
}

      
      





نحن بحاجة إلى تنفيذ التبديل بين هذه الكائنات على الخريطة. لكن كيف يمكننا القيام بذلك بدون إحداثيات؟ لا يمكن. لذلك ، نحتاج بطريقة ما إلى الحصول على هذه الإحداثيات. للقيام بذلك ، سوف نستخدم خدمة Nominatim من OpenStreetMap. للحصول على معلومات حول كيفية تكوين سلسلة استعلام بشكل صحيح ، انظر هنا . سأعرض فقط أحد الخيارات الممكنة.



لذلك ، قمنا بإنشاء حاوية للعناوين في الترميز:



<div id="addresses"></div>

      
      





إعادة كتابة script.js:



//    
const $addresses = document.getElementById('addresses')

;(async () => {
  //    
  const response = await fetch('./db/addresses.json')
  const addresses = await response.json()

  //   
  for (const place in addresses) {
    //  
    const $button = document.createElement('button')

    $button.textContent = place

    //  
    const address = addresses[place]

    //   
    const query = address.replace(
      /([--]+)\s([--]+),\s([0-9--]+)/,
      '$3+$1+$2,+'
    )
    // , , 2++,+

    //     data-
    $button.dataset.address = address
    $button.dataset.query = query

    $addresses.append($button)
  }
})()

//   
$addresses.addEventListener('click', async ({ target }) => {
  if (target.tagName !== 'BUTTON') return

  //    data-
  const { address, query } = target.dataset

  //    
  const response = await fetch(
    `https://nominatim.openstreetmap.org/search?q=${query}&format=json&limit=1`
  )
  // format -  , limit -    

  //  ,   
  const { display_name, lat, lon } = (await response.json())[0]

  //   
  const name = display_name.match(/[--\s(«\-»)]+/)[0]

  const position = [lat, lon]

  //  
  const tooltip = `${name}<br>${address}`

  //  
  getMap(position, tooltip)
})

      
      





افتح index.html. عندما تضغط على الزر الأول ، نحصل على الفور على موضع واسم المسرح. عندما تضغط على الزر الثاني والأزرار اللاحقة ، نتحرك بسلاسة بين المسارح.







رائع. كل شيء يعمل كما هو متوقع.



على هذا ، دعني آخذ إجازتي. أتمنى أن تجد شيئًا مثيرًا للاهتمام لنفسك. شكرا لك على اهتمامك واستمتع بيومك.



All Articles