Привет, это моя первая статья здесь, добро пожаловать на мой Tech talk.
Некоторое время назад, пытаясь заказать поездку из мобильного приложения uber, я перемещался по страницам и задавался вопросом, как был разработан и внедрен поток интерфейса для пассажиров. Я увидел в этом вызов и решил попробовать сделать клон веб-версии. К счастью для меня, во время исследования я наткнулся на веб-версию приложения (о существовании которой я даже не подозревал) и решил сделать ее копию.
В этой статье я расскажу вам, как я создал клон интерфейса пассажирского веб-приложения Uber с помощью ReactJS и Typescript.
Обратите внимание: это не учебник и не объяснение кода, поэтому в статье не будет подробных фрагментов кода.
Начнем с перечисления технологий (языки, фреймворки и API), использованных в процессе сборки.
-
ReactJS с инструментарием Redux.
-
Typescript.
-
Tailwind.
-
Компонент Tailwind CSS и стили.
-
IP Geo-location API.
-
API карты Google.
-
Firebase API для аутентификации.
- React с инструментарием Redux.
- Typescript.
- Tailwind CSS и стилизованный компонент.
- IP Geo-location API.
- API карты Google.
- Firebase API для аутентификации.
- КЛЮЧЕВЫЕ ОСОБЕННОСТИ И ИХ РЕАЛИЗАЦИЯ.
- Макет карты.
- Автозаполнение мест.
- Код страны.
- Текущая геолокация пользователя.
- Хранение данных о местоположении пункта приема и назначения.
- API Direction.
- Матрица расстояний
- Заключение.
React с инструментарием Redux.
Из-за моего опыта работы с ReactJS и некоторой гибкости, которой он обладает, я решил придерживаться его при создании этого проекта. С другой стороны, Redux-toolkit стал моим любимым инструментом для управления глобальными состояниями, поскольку он очень удобен в обслуживании, обеспечивает простоту тестирования и полезен при рендеринге на стороне сервера.
Все глобальные состояния, такие как значение и координаты начальной позиции пользователя, значение и координаты пикапа и значение пункта назначения, управляются с помощью Redux-toolkit.
Typescript.
С его помощью я смог определить типы данных, используемые в каждом компоненте, и выявить ошибки на ранней стадии.
Tailwind CSS и стилизованный компонент.
Услышав разговоры о Tailwind CSS и его широких возможностях кастомизации, я решил попробовать. Помимо высоких возможностей настройки, в процессе работы над проектом я смог быстрее создавать сложные отзывчивые макеты и писать общие шаблоны утилит. Более того, стилизованные компоненты позволили мне стилизовать мои пользовательские компоненты и предотвратить ошибки в именах классов.
Несмотря на то, что этот проект был первым проектом, в котором я их применил, я все равно смог добиться легкой поддерживаемости стиля моей кодовой базы.
IP Geo-location API.
С помощью IP Geolocation вы можете получить подробную информацию о конкретном пользователе, например, название континента, название округа, города, код страны, валюту и так далее, основываясь на IP-адресе пользователя. Моя цель использования этого API в данном проекте заключалась в получении доступа к текущему коду страны пользователя. Этот код страны использовался вместе с данными пользовательского запроса при попытке получить результат автозаполнения места при поиске. Подробнее об этом я расскажу позже в этой статье.
API карты Google.
Все динамические карты, маршруты-направления, автозаполнение мест, матрица расстояний и текущее местоположение водителя были реализованы с помощью API карт Google. Попробуйте дочитать статью до конца, чтобы узнать больше подробностей об этом.
Firebase API для аутентификации.
Я решил сделать все проще, используя интеграцию с федеративным поставщиком идентификационных данных для Firebase. Пользователи могут войти в приложение с помощью своих учетных записей Facebook или Google.
КЛЮЧЕВЫЕ ОСОБЕННОСТИ И ИХ РЕАЛИЗАЦИЯ.
Макет карты.
Если вы знакомы с использованием Google Maps в качестве разработчика, вы заметите, что макет карты по умолчанию сильно отличается от макета карты в веб-приложении Uber. Я смог добиться этого, используя «Справочник стилей для карт», чтобы подражать Uber. С помощью опции стиля из документов Google Maps Docs вы можете легко настроить представление стандартных стилей карт Google, изменив визуальное отображение таких объектов, как дороги, парки, предприятия и другие точки интереса.
Я использовал декларацию стиля JSON
, чтобы изменить цвет геометрии административной заливки, геометрии ландшафтной заливки и геометрии заливки poi. Кроме того, я смог установить видимость дороги, скрыть естественный ландшафт, убрать всю интенсивность из цвета пои и так далее, как показано в базе кода здесь.
Посмотрите фрагмент кода ниже, чтобы иметь представление о том, как это было сделано.
[
{
"featureType": "all",
"stylers": [
{ "color": "#C0C0C0" }
]
},{
"featureType": "road.arterial",
"elementType": "geometry",
"stylers": [
{ "color": "#CCFFFF" }
]
},{
"featureType": "landscape",
"elementType": "labels",
"stylers": [
{ "visibility": "off" }
]
}
]
Вы можете объявить переменную массива и установить ее в качестве стиля в опции карты.
Автозаполнение мест.
Функция автозаполнения в платформе Google Maps Platform обеспечивает поведение поиска в поле поиска Google Maps.
Библиотека Place Auto-complete JavaScript была обычным способом реализации функции автозаполнения при работе над веб-приложением. Однако использование этой уже готовой библиотеки имеет некоторые ограничения.
Я рассмотрел возможность использования веб-сервиса Place auto-complete, который, как мне кажется, будет наиболее подходящим для достижения моей цели. Благодаря этому я могу настраивать стиль отображаемого результата, в отличие от использования JavaScript-библиотеки Place autocomplete.
Служба автозаполнения Places возвращает предсказание места в ответ на запрос HTTP
. В запросе указывается текстовая строка поиска и необязательные географические границы. Этот сервис может быть использован для обеспечения функциональности автозаполнения для текстового географического поиска, возвращая такие места, как предприятия, адреса и точки интереса по мере ввода пользователем типа.
Параметры, которые я использовал для выполнения этого простого действия, — это ввод, который представляет собой текстовую строку для поиска, страна, которая ограничит результат поиска местами в пределах страны пользователя, и, конечно, уникальный ключ API.
Приведенный ниже фрагмент кода дает наглядное представление о том, как это было сделано.
const getPredictions = (input:string) => {
axios(`https://maps.googleapis.com/maps/api/place/autocomplete/json?input=${input}&components=country:${countryCode !==null?countryCode:'NG' }&key=${GOOGLE_API_KEY}`, {
method: "GET",
headers: {
"Content-Type": "application/json"
}
})
.then( async res => {
try {
const response = await res.data;
const result = response.predictions;
return result;
}catch (error) {
console.log(error);
}})
}
Приведенный выше code
возвращает массив объектов в качестве прогнозируемого результата.
Код страны.
Наличие динамического кода страны не было тем, что я изначально считал необходимым, но потом я передумал.
Согласно моему мнению о том, как был создан Uber, код страны, используемый для получения прогнозируемого результата, определенно будет основан на местоположении пользователя. Подумав об этом, я решил поискать способ получить код страны пользователя сразу же после ввода поискового запроса. Проведя некоторые исследования, я наткнулся на IP Geolocation, которая обеспечивает точный ответ в режиме реального времени.
Следуя этой конечной точке https://api.ipgeolocation.io/ipgeo
и используя следующий подход,
const getCountryCode = (IP_KEY) = > {
fetch(`https://api.ipgeolocation.io/ipgeo?apiKey=${IP_KEY}`)
.then( async res => {
try {
const result = await res.json();
return result;
}catch (error) {
console.log(error);
}
})
}
возвращается ответ объекта JSON
, содержащий IP, имя хоста, город, код страны и так далее, как показано ниже.
{
"ip": "8.8.8.8",
"hostname": "dns.google",
"city": "Lagos",
"country_code2": "NG",
...others
}
Код страны_code2, который является кодом страны пользователя, теперь установлен в качестве параметра страны конечной точки автозаполнения места.
Текущая геолокация пользователя.
В конце 2016 года компания uber выпустила обновление, позволяющее приложению отслеживать данные о местоположении пользователя в любое время, что, по их словам, повысит точность подбора и высадки пассажиров. Реализация этой функции была довольно простой, поскольку я хорошо знаком с использованием метода getCurrentPosition
. С помощью getCurrentPosition я смог получить текущее местоположение устройства конкретного пользователя в терминах его координат (широта и долгота).
if(navigator.geolocation){
navigator.geolocation.getCurrentPosition(
(position: GeolocationPosition) => {
const { latitude, longitude } = position.coords;
console.log(latitude, longitude);
}
)
}
Приведенный выше фрагмент регистрирует текущую широту
и долготу
местоположения устройства конкретного пользователя.
Совершенно очевидно, что эта форма данных будет наиболее удобна для пользователей, если отображается в формате адреса. С помощью обратного геокодирования я смог добиться этого.
Хранение данных о местоположении пункта приема и назначения.
Если внимательно посмотреть на веб-приложение Uber, то все данные о местах приема и назначения (название адреса, координаты и ID места) хранились в виде параметра URL. Такой подход оказался весьма полезным в том смысле, что при каждом обновлении я сохраняю состояние ввода местоположения и информационного окна.
API Direction.
API направления — это сервис, который использует HTTP
запрос для возврата наиболее эффективных маршрутов. Для упрощения создания рендеринга направлений я использовал библиотеку Direction API для JavaScript.
С ее помощью я смог создать экземпляр сервиса направления и проложить маршрут, передав в качестве аргумента объект, состоящий из пункта отправления, пункта назначения, режима поездки и вариантов движения. Чтобы увидеть, как я это сделал, посмотрите фрагмент из кодовой базы проекта ЗДЕСЬ
Матрица расстояний
Продолжительность поездки и время высадки были рассчитаны с помощью API матрицы расстояний. Этот API возвращает информацию, основанную на рекомендательном маршруте между начальной и конечной точкой.
const getDistance = (origin, end) => {
axios(`https://maps.googleapis.com/maps/api/distancematrix/json?origins=${origin}&destinations=${end}&units=imperial&key=${GOOGLE_API_KEY}`, {
method: "GET",
headers: {
"Content-Type": "application/json"
}
})
.then(async res => {
try {
const response = await res;
const {data} = await response;
const result = data.rows[0].elements[0];
return result;
}
catch (error:any) {
console.log(error);
}
});
}
Из приведенного выше фрагмента функция возвращает длительность, которая представляет собой объект с текстом и значением в качестве ключа. Текст использовался для расчета продолжительности и времени высадки в пути. Значение, с другой стороны, использовалось для расчета цен на каждую поездку.
В обычных условиях продолжительность и стоимость поездки можно получить непосредственно из конечных точек API uber estimate-time и uber estimate-price соответственно. Однако на момент разработки на это наложено множество ограничений.
Заключение.
Спасибо, что дочитали до конца, многое уже было сказано. Однако невозможно описать все детали процесса разработки. Вы всегда можете обратиться к кодовой базе на GitHub ЗДЕСЬ для получения более подробной информации.
Это всего лишь краткое описание того, как я создал свою версию убер-клона, я приветствую любую форму критики, а также исправления. Спасибо.