urbi-exhibitions
Version:
401 lines (292 loc) • 14.4 kB
Markdown
# urbi-exhibitions
## Установка
`npm i urbi-exhibitions`
## Использование
Для использования компонентов и сценариев необходимо сделать следующие шаги:
1. Задать в приложении цвета в конфиге `tailwind` как в [примере](../demo/tailwind.config.js);
2. Добавить в конфиг `tailwind` в `content` `'./node_modules/urbi-exhibitions/dist/**/*.{js,mjs,ts,jsx,tsx}'`;
3. Обернуть приложение в необходимые контексты
## Состав библиотеки
### [Типы](./src/types.ts)
Базовые типы, используемые в навигации: `Coordinates, Point, RoutePart, Route`
Пример использования:
```
import type { Point, Coordinates } from "urbi-exhibitions"
```
### [Контексты](./src/contexts)
- **[ExhibitionContext](./src/contexts/exhibitionContext.tsx)** — Общий контекст для проброса параметров между основным приложением и библиотекой;
Пример использования:
```
import { ExhibitionContextProvider } from 'urbi-exhibitions/contexts';
const { theme } = useTheme();
const { t } = useTranslation();
return (
<ExhibitionContextProvider
theme={theme}
t={t} // Либо не передаем вовсе, если в приложении отсутствует мультиязычность
>
// code
</ExhibitionContextProvider>
);
```
- **[MapContext](./src/contexts/mapContext.tsx)** — Хранит в себе объект map c экземпляром карты, gltf плагина и основные параметры состояния карты. До момента загрузки карты map = undefined.
```
interface MapContextState {
map?: {
instance: Map
gltfPlugin: GltfPlugin;
state: MapState
}
}
interface MapState {
zoom: number;
isDragging: boolean;
floorLevels: FloorLevel[];
floorLevelIndex?: number;
floorLevelName?: string;
floorPlanId?: string;
}
```
Примеры использования:
```
import { MapProvider } from "urbi-exhibitions/contexts"
function App() {
return (
<MapProvider>
...
</MapProvider>
)
}
```
```
import { useMap } from "urbi-exhibitions/contexts"
function SomeComponent() {
const { map } = useMap()
}
```
- **[GeolocationContext](./src/contexts/geolocationContext.tsx)** — Хранит в себе текущие координаты клиента при включенном отслеживании координат (см. компонент LocationTracker).
```
interface GeolocationContextState {
coordinates?: GeolocationCoordinates;
}
```
Примеры использования:
```
import { GeolocationProvider } from "urbi-exhibitions/contexts"
function App() {
return (
<GeolocationProvider>
...
</GeolocationProvider>
)
}
```
```
import { useGeolocation } from "urbi-exhibitions/contexts"
function SomeComponent() {
const { coordinates } = useGeolocation()
}
```
- **[RoutingApiContext](./src/contexts/routingApiContext.tsx)** — Используется для передачи в компоненты приложения экземпляра Routing API, созданного при помощи функции createRoutingApi.
Примеры использования:
```
import { routingApi } from "./routingApi.ts"
import { RoutingApiProvider } from "urbi-exhibitions/contexts"
function App() {
return (
<RoutingApiProvider routingApi={routingApi}>
...
</RoutingApiProvider>
)
}
```
```
import { useRoutingApi } from "urbi-exhibitions/contexts"
function SomeComponent() {
const { queries, baseUrl } = useRoutingApi()
}
```
### [Routing API](./src/api/routing)
Для использования Routing API в проекте, необходимо создать его экземпляр:
```
import { createRoutingApi } from "urbi-exhibitions/api"
const routingApi = createRoutingApi({ apiKey: "YOUR_API_KEY" })
```
- **[Get route](./src/api/routing/getRoute/)** — Метод, который строит маршрут из точки А в точку Б. Также есть возможность указания промежуточных точек. [Подробнее](https://docs.2gis.com/ru/api/@balady-tech/navigation/routing/reference/routing) в документации к API.
Пример использования с react-query:
```
const { data } = useQuery(routingApi.queries.getRoute({ points: [...] }))
```
Условный запрос маршрута:
```
const { data } = useQuery({
...routingApi.queries.getRoute({ points: [...] }),
enabled: !someCheck,
// Также можно переопределять другие параметры хука useQuery (кэшировани и т.д.)
})
```
### [Хуки](./src/hooks)
- **[useChunks](./src/hooks/useChunks/)** — Разбивает массив элементов на несколько массивов указанной длины
- **[useGltfModels](./src/hooks/useGltfModels/)** — При помощи gltf плагина добавляет указанные модели на карту
- **[usePartnerLogos](./src/hooks/usePartherLogos/)** — Добавляет на карту логотипы партнеров, через проп параметр `floorLevelIndexes` можно указать на каких этажах логотипы должны отображаться.
### [Utils](./src/utils)
- **[getRouteKey](./src/hooks/useChunks/)** — Создает ключ, которые используется в react-query для запроса Get route
- **[parseLineStringWKT](./src/utils/parseLineStringWKT.ts)** — Парсит строку типа `LINESTRING(...)` и возвращает массив чисел
- **[toChunks](./src/utils/toChunks.ts)** — Разбивает массив на массивы указанной длины. Используется в основе хука `useChunks`
### [Компоненты](./src/components)
- **[PlayButton](./src/components/playButton)** — Кнопка play;
- **[MapContainer](./src/components/mapContainer/)** — Компонент для отрисовки карты. Отрисовывает карту внутри себя и сохраняет инстанс карты в MapContext. Также осуществляет подписку на некоторые события карты (изменение зума, переключение этажей) для обновления соответствующих данных в MapContext. Есть возможность передать URL локально скрипта для работы карт без подключения к сети. Также можно подписаться на событие загрузки карты, чтобы загрузить стили и т.д.
Пример использования с react-query:
```
import { MapProvider } from "urbi-exhibitions/contexts"
import { MapContainer } from "urbi-exhibitions/components"
import { useCallback } from "react"
import type { Map, MapOptions } from "@2gis/mapgl/types"
const API_KEY = "YOUR_API_KEY"
const DEFAULT_OPTIONS: MapOptions = { zoom: 30, center: [37.617734, 55.751999], floorControl: 'centerRight' }
function App() {
const onLoad = useCallback(({ instance }: { instance: Map }) => {
// Тут можно загрузить какие-то стили для карты и др.
}, [])
return (
<MapProvider>
<MapContainer
className="fixed inset-0"
apiKey={API_KEY}
options={DEFAULT_OPTIONS}
onLoad={onLoad}
/>
</MapProvider>
)
}
export default App
```
#### Кеширование тайлов
Есть возможность включить кеширование тайлов карты, что позволяет приложению работать в оффлайн-режиме или существенно ускорить загрузку при повторных посещениях. Кэширование реализовано через Service Worker API с поддержкой TTL (времени жизни) для кэшированных тайлов.
Для включения кэширования тайлов:
- Добавьте параметр `tilesCache={true}` в компонент MapContainer
- Настройте Vite-плагин для генерации Service Worker
```
// App.tsx
import { MapProvider } from "urbi-exhibitions/contexts"
import { MapContainer } from "urbi-exhibitions/components"
const API_KEY = "YOUR_API_KEY"
function App() {
return (
<MapProvider>
<MapContainer
apiKey={API_KEY}
tilesCache={true} // Включение кеширования
/>
</MapProvider>
);
}
```
```
// vite.config.js
import { defineConfig } from 'vite';
import { tilesCacheSwPlugin } from 'urbi-exhibitions/plugins';
export default defineConfig({
plugins: [
// ..другие плагины
tilesCacheSwPlugin({
cacheName: 'my-tiles-cache',
// URL адреса запросы которого необходимо кешировать, опционально, по умолчанию '2gis.com'
requiredRequestUrl: '2gis.com',
// Время жизни кеша, опционально, по умолчанию 1 день
ttl: 1000 * 60 * 60 * 24,
}),
]
});
```
Очистка кеша:
```
import { clearTilesCache } from 'urbi-exhibitions/clientSW';
function ClearCacheButton() {
const handleClearCache = async () => {
await clearTilesCache();
console.log('Кэш тайлов очищен');
};
return <button onClick={handleClearCache}>Очистить кэш</button>;
}
```
Также можно добавить параметр ?cache=clear в URL приложения для очистки кэша при загрузке страницы.
- **[LocationTracker](./src/components/locationTracker/)** — Компонент, который отслеживает изменение местоположения пользователя и сохраняет его в GeolocationContext. Соответственно, должен использоваться внутри данного контекста. Есть параметры для настройки debounce эффекта, позволяющего регулировать частоту обновления координат в контексте для предотвращения слишком частых перерисовок. На все приложение должно существовать не более одного экземпляра данного компонента. Функционал выполнен в виде компонента для возможности условной отрисовки (отслеживание местоположения пользователя по условию, чтобы запрашивать права на получение местоположения у пользователя только когда это действительно необходимо).
Пример использования:
```
import { LocationTracker } from "urbi-exhibitions/components"
function SomeComponent() {
return {
<LocationTracker/>
}
}
```
- **[FloorControl](./src/components/floorControl/)** — Компонент для переключения этажа.
Пример использования:
```
import { FloorControl } from "urbi-exhibitions/components"
import { useMap } from "urbi-exhibitions/contexts"
const SomeComponent = () => {
const { map } = useMap()
return (
<FloorControl.Root className="">
{map?.state.floorLevels.map(({ floorLevelIndex, floorLevelName }) => (
<FloorControl.Button
key={floorLevelIndex}
floorLevelIndex={floorLevelIndex}
className=""
>
{floorLevelName}
</FloorControl.Button>
))}
</FloorControl.Root>
)
}
```
### [Сценарии](./src/contexts)
- **[ImmersiveScenario](./src/scenarios/immersive)** — [Иммерсивный сценарий](https://urbi-ae.github.io/exhibitions/#/immersive)
Пример использования целиком можно посмотреть [demo](../demo/src/pages/immersive).
- **[QuizScenario](./src/scenarios/quiz)** — [Квиз сценарий](https://urbi-ae.github.io/exhibitions/#/quiz)
Пример использования целиком можно посмотреть [demo](../demo/src/pages/quiz).
#### Модули:
1. **[flyOverImmersiveBuilding](./src/scenarios/immersive/modules/flyOverImmersiveBuilding.ts)** — Полет над зданием;
#### Компоненты:
1. **[ComplexCard](./src/scenarios/immersive/components/complexCard)** — Карточка здания (вне маркера);
2. **[PovPagination](./src/scenarios/immersive/components/povPagination)** — Пагинация для pov'ов здания;
### [Модули](./src/modules)
- **[MapFlight](./src/modules/mapFlight.ts)** — полеты карты;
Пример использования:
```
import { MapFlight } from 'urbi-exhibitions/modules';
const mapFlight = new MapFlight({
zoom: MAP_ZOOM,
maxZoom: MAP_MAX_ZOOM,
minZoom: MAP_MIN_ZOOM,
center: MAP_CENTER,
pitch: MAP_PITCH,
rotation: MAP_ROTATION,
});
mapFlight.runFlight(map, config);
```
- **[convertModelToCS, convertModelParams](./src/modules/convertModel.ts)** — вспомогательные утилиты для конвертации конфигов иммерсивных моделей;
Пример использования:
```
import { convertModelToCS } from 'urbi-exhibitions/modules';
convertModelToCS({
buildingIds: ['70030076151587939', '70030076299034544'],
coords: [54.607139, 24.483673],
scale: 1,
rotateX: 0,
rotateZ: -0.10300000000000001,
rotateY: 0,
moveX: 0,
moveY: 0,
moveZ: 0,
models: [
{
path: getModelUrl('ml/ferrari_gloss.glb'),
name: 'ferrari',
},
],
});
```