[Разработка веб-сайтов, JavaScript, Программирование] JavaScript за 60 секунд: работаем с картой (Geolocation API, Leaflet.js, Nominatim)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Доброго времени суток, друзья!
В этом небольшом туториале мы вместе с вами выполним три простых задания:
- С помощью Geolocation API и Leaflet.js определим текущее местоположение пользователя и отобразим его на карте
- Реализуем анимированный переход между городами
- Реализуем переключение между адресами с предварительным получением названия объекта и его координат
Код проекта находится здесь.
Поиграть с кодом можно здесь:
Извините, данный ресурс не поддреживается. :(
Определяем текущее местоположение пользователя
Geolocation API позволяет пользователю предоставлять веб-приложению данные о своем местоположении. В приложении для запроса этих данных используется метод Geolocation.getCurrentPosition(). Данный метод принимает один обязательный и два опциональных параметра: success — функция обратного вызова, получающая объект Position при предоставлении разрешения, error — функция обратного вызова, получающая объект PositionError при отказе в доступе, и options — объект с настройками. Вот как это выглядит в коде:
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 Maps и 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/addresses.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. При нажатии первой кнопки сразу получаем позицию и название театра. При нажатии второй и последующих кнопок плавно перемещаемся между театрами.
Круто. Все работает, как ожидается.
На этом позвольте откланяться. Надеюсь, вы нашли для себя что-нибудь интересное. Благодарю за внимание и хорошего дня.
===========
Источник:
habr.com
===========
Похожие новости:
- [Биографии гиков, Игры и игровые приставки] Умер Эрик Энгстром, легенда игровой разработки Microsoft и автор DirectX
- [Разработка под iOS, Разработка мобильных приложений, Swift] Чаты на вебсокетах в iOS, если у вас WAMP
- [JavaScript, Node.JS, Amazon Web Services, ReactJS, Облачные сервисы] Serverless шагает по планете. Сравним SberCloud и AWS
- [Совершенный код, Проектирование и рефакторинг, TDD, Программирование микроконтроллеров, Agile] Двигайся быстрее и ломай преграды? Не так быстро, когда дело касается встраиваемых систем (перевод)
- [PHP, Программирование] Отпусти меня, PHP
- [Разработка веб-сайтов, PHP, Laravel] Laravel–Дайджест (6–13 декабря 2020)
- [Производство и разработка электроники, Смартфоны, IT-компании] В Индии на фабрике по сборке iPhone сотрудники устроили погром из-за неполной выплаты им зарплаты
- [Программирование микроконтроллеров] Что делать, если ты уже научился программировать микроконтроллеры?
- [Разработка веб-сайтов, Google Chrome, Браузеры, Тестирование веб-сервисов] Обходим проверку сертификата SSL
- [Спортивное программирование] Russian AI Cup 2019. 4 место, почти не умея программировать или о пользе soft skills
Теги для поиска: #_razrabotka_vebsajtov (Разработка веб-сайтов), #_javascript, #_programmirovanie (Программирование), #_javascript, #_programmirovanie (программирование), #_razrabotka (разработка), #_map, #_karta (карта), #_geolocation_api, #_geolocation, #_geolokatsija (геолокация), #_opredelenie_mestopolozhenija (определение местоположения), #_leaflet.js, #_google_maps, #_openstreetmap, #_razrabotka_vebsajtov (
Разработка веб-сайтов
), #_javascript, #_programmirovanie (
Программирование
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 21-Ноя 23:05
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Доброго времени суток, друзья! В этом небольшом туториале мы вместе с вами выполним три простых задания:
Код проекта находится здесь. Поиграть с кодом можно здесь: Извините, данный ресурс не поддреживается. :( Определяем текущее местоположение пользователя Geolocation API позволяет пользователю предоставлять веб-приложению данные о своем местоположении. В приложении для запроса этих данных используется метод Geolocation.getCurrentPosition(). Данный метод принимает один обязательный и два опциональных параметра: success — функция обратного вызова, получающая объект Position при предоставлении разрешения, error — функция обратного вызова, получающая объект PositionError при отказе в доступе, и options — объект с настройками. Вот как это выглядит в коде: 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 Maps и 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/addresses.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. При нажатии первой кнопки сразу получаем позицию и название театра. При нажатии второй и последующих кнопок плавно перемещаемся между театрами. Круто. Все работает, как ожидается. На этом позвольте откланяться. Надеюсь, вы нашли для себя что-нибудь интересное. Благодарю за внимание и хорошего дня. =========== Источник: habr.com =========== Похожие новости:
Разработка веб-сайтов ), #_javascript, #_programmirovanie ( Программирование ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 21-Ноя 23:05
Часовой пояс: UTC + 5