Заказ в пути
Положение курьера обновляется вдоль дорожного маршрута. Карта и остальные слои остаются на месте.
- Запустите пример и следите за синей меткой.
- Можно перемещать карту: обновление координат не сбрасывает камеру.
import * as sdk from "@umap-llc/map-react";
// HTML: <div id="map" style="height:480px;position:relative"></div>
const map = sdk.createMap({
container: "map",
style: "YOUR_STYLE_URL",
accessToken: "YOUR_ACCESS_TOKEN",
center: [71.423, 51.128],
zoom: 14,
});
async function setupExample(map, sdk, report = console.log) {
const response = await fetch(
"https://developer.umap.kz/examples/data/trip.geojson",
);
if (!response.ok) throw new Error("Не удалось загрузить поездку");
const trip = await response.json();
const path = trip.features[0].geometry.coordinates;
await map.addSource("trip", { type: "geojson", data: trip });
map.addLayer({
id: "trip-line",
type: "line",
source: "trip",
"rendering-order": "overlay",
paint: {
"line-color": "#1769e0",
"line-width": 4,
"line-opacity": 0.65,
},
});
await map.addSource("courier", {
type: "geojson",
data: { type: "FeatureCollection", features: [] },
});
map.addLayer({
id: "courier-halo",
type: "circle",
source: "courier",
"rendering-order": "overlay",
paint: { "circle-radius": 12, "circle-color": "#fff" },
});
map.addLayer({
id: "courier-dot",
type: "circle",
source: "courier",
"rendering-order": "overlay",
paint: { "circle-radius": 8, "circle-color": "#1769e0" },
});
map.fitBounds(
[
[71.399, 51.122],
[71.438, 51.14],
],
{ padding: 65, maxZoom: 14.5 },
);
const distances = [0];
for (let i = 1; i < path.length; i++)
distances.push(
distances[i - 1] +
Math.hypot(
(path[i][0] - path[i - 1][0]) * 0.63,
path[i][1] - path[i - 1][1],
),
);
const start = performance.now();
let frame = 0;
const update = () => {
const progress = Math.min(1, (performance.now() - start) / 45000);
const d = progress * distances[distances.length - 1];
let i = 0;
while (i < path.length - 2 && distances[i + 1] < d) i++;
const t = Math.min(
1,
(d - distances[i]) / (distances[i + 1] - distances[i] || 1),
);
const p = [
path[i][0] + (path[i + 1][0] - path[i][0]) * t,
path[i][1] + (path[i + 1][1] - path[i][1]) * t,
];
map.setData("courier", {
type: "FeatureCollection",
features: [
{
type: "Feature",
properties: {},
geometry: { type: "Point", coordinates: p },
},
],
});
if (progress < 1) frame = requestAnimationFrame(update);
else report("Курьер прибыл");
};
report("Курьер в пути · заказ №1042");
update();
return () => cancelAnimationFrame(frame);
}
map.once("load", async () => {
const cleanup = await setupExample(map, sdk);
if (cleanup) map.once("remove", cleanup);
});
Как запустить у себя
В JavaScript укажите Style URL и ключ своей карты. Код запускайте в проекте со сборщиком. Во Flutter сохраните пример в lib/main.dart и передайте UMAP_STYLE_URL и UMAP_ACCESS_TOKEN через --dart-define.
Примеры со своими данными загружают подготовленные GeoJSON и изображения. Замените их файлами вашего приложения. Для Flutter-примеров с загрузкой файлов добавьте зависимость: flutter pub add http.