Routes
Draw lines and paths connecting coordinates on the map.
Use MapRoute to draw lines connecting a series of coordinates. Perfect for showing directions, trails, or any path between points.
Basic Route
Draw a route with numbered stop markers along the path.
import {
Map,
MapMarker,
MarkerContent,
MarkerTooltip,
MapRoute,
} from "@/components/ui/map";
const route = [
[116.3972, 39.9075], // Tiananmen
[116.3974, 39.9163], // Forbidden City
[116.3914, 40.0089], // Bird's Nest
[116.2755, 40.0003], // Summer Palace
] as [number, number][];
const stops = [
{ name: "Tiananmen", lng: 116.3972, lat: 39.9075 },
{ name: "Forbidden City", lng: 116.3974, lat: 39.9163 },
{ name: "Bird's Nest", lng: 116.3914, lat: 40.0089 },
{ name: "Summer Palace", lng: 116.2755, lat: 40.0003 },
];
export function RouteExample() {
return (
<div className="h-[400px] w-full">
<Map center={[116.35, 39.97]} zoom={10.5}>
<MapRoute coordinates={route} color="#3b82f6" width={4} opacity={0.8} />
{stops.map((stop, index) => (
<MapMarker key={stop.name} longitude={stop.lng} latitude={stop.lat}>
<MarkerContent>
<div className="size-4.5 rounded-full bg-blue-500 border-2 border-white shadow-lg flex items-center justify-center text-white text-xs font-semibold">
{index + 1}
</div>
</MarkerContent>
<MarkerTooltip>{stop.name}</MarkerTooltip>
</MapMarker>
))}
</Map>
</div>
);
}
Dashed Route
Use dashed to render a dashed stroke style.
"use client";
import { Map, MapRoute, MapMarker, MarkerContent, MarkerTooltip } from "@/components/ui/map";
const route: [number, number][] = [
[116.3972, 39.9075],
[116.4300, 39.9163],
[116.4600, 39.9350],
[116.4800, 39.9600],
];
const stops = [
{ name: "Start: Tiananmen", lng: 116.3972, lat: 39.9075 },
{ name: "End: Chaoyang", lng: 116.4800, lat: 39.9600 },
];
export function DashedRouteExample() {
return (
<div className="h-[400px] w-full">
<Map center={[116.4400, 39.9350]} zoom={11.5}>
<MapRoute
coordinates={route}
color="#f59e0b"
width={3}
opacity={0.9}
dashed
/>
{stops.map((stop) => (
<MapMarker key={stop.name} longitude={stop.lng} latitude={stop.lat}>
<MarkerContent>
<div className="size-3 rounded-full bg-amber-500 border-2 border-white shadow-lg" />
</MarkerContent>
<MarkerTooltip>{stop.name}</MarkerTooltip>
</MapMarker>
))}
</Map>
</div>
);
}Route Planning
Display multiple route options and let users select between them. This example fetches real driving directions from the OSRM API. Click on a route or use the buttons to switch.
"use client";
import { useState } from "react";
import { Map, MapRoute, MapMarker, MarkerContent } from "@/components/ui/map";
const routeOptions = [
{
id: "highway",
label: "高速路线",
color: "#3b82f6",
coordinates: [
[116.397428, 39.90923],
[116.41, 39.91],
[116.45, 39.92],
[116.48, 39.97],
[116.5, 40.02],
] as [number, number][],
duration: "32 分钟",
distance: "18.4 公里",
},
{
id: "city",
label: "城区路线",
color: "#10b981",
coordinates: [
[116.397428, 39.90923],
[116.415, 39.915],
[116.43, 39.93],
[116.45, 39.96],
[116.5, 40.02],
] as [number, number][],
duration: "48 分钟",
distance: "16.1 公里",
},
{
id: "scenic",
label: "景观路线",
color: "#f59e0b",
coordinates: [
[116.397428, 39.90923],
[116.38, 39.92],
[116.37, 39.95],
[116.4, 40.0],
[116.5, 40.02],
] as [number, number][],
duration: "55 分钟",
distance: "20.7 公里",
},
];
const origin = { lng: 116.397428, lat: 39.90923, name: "天安门" };
const destination = { lng: 116.5, lat: 40.02, name: "北京东站" };
export function OsrmRouteExample() {
const [activeRoute, setActiveRoute] = useState(routeOptions[0].id);
const selected = routeOptions.find((r) => r.id === activeRoute)!;
return (
<div className="h-full w-full relative">
<Map center={[116.44, 39.96]} zoom={11}>
{routeOptions.map((route) => (
<MapRoute
key={route.id}
coordinates={route.coordinates}
color={route.id === activeRoute ? route.color : "#9ca3af"}
width={route.id === activeRoute ? 5 : 3}
opacity={route.id === activeRoute ? 0.9 : 0.4}
/>
))}
<MapMarker longitude={origin.lng} latitude={origin.lat}>
<MarkerContent>
<div className="size-5 rounded-full bg-green-500 border-2 border-white shadow-lg flex items-center justify-center text-white text-xs font-bold">
A
</div>
</MarkerContent>
</MapMarker>
<MapMarker longitude={destination.lng} latitude={destination.lat}>
<MarkerContent>
<div className="size-5 rounded-full bg-red-500 border-2 border-white shadow-lg flex items-center justify-center text-white text-xs font-bold">
B
</div>
</MarkerContent>
</MapMarker>
</Map>
<div className="absolute top-4 right-4 bg-white/95 backdrop-blur-sm rounded-lg p-3 shadow-lg text-sm border border-gray-100">
<div className="flex items-center gap-2 mb-2">
<span
className="size-2 rounded-full shrink-0"
style={{ backgroundColor: selected.color }}
/>
<span className="font-medium text-gray-900 text-[13px]">
{selected.label}
</span>
</div>
<div className="text-gray-500 text-xs leading-relaxed">
{selected.distance} · {selected.duration}
</div>
</div>
<div className="absolute bottom-4 left-4 right-4 sm:left-1/2 sm:right-auto sm:-translate-x-1/2 sm:w-auto flex gap-2 bg-white/95 backdrop-blur-sm rounded-xl p-2 shadow-lg border border-gray-100">
{routeOptions.map((route) => (
<button
key={route.id}
onClick={() => setActiveRoute(route.id)}
className="relative flex-1 sm:flex-none flex items-center gap-2.5 px-3 py-2 rounded-lg text-left transition-colors cursor-pointer"
style={{
backgroundColor:
activeRoute === route.id
? `${route.color}10`
: "transparent",
}}
>
<span
className="absolute left-0 top-1/2 -translate-y-1/2 w-[3px] h-5 rounded-full"
style={{
backgroundColor:
activeRoute === route.id ? route.color : "#d1d5db",
}}
/>
<div className="pl-1.5">
<div className="text-xs text-gray-500 leading-tight">
{route.label}
</div>
<div
className="text-[15px] font-semibold leading-snug"
style={{
color:
activeRoute === route.id ? route.color : "#374151",
}}
>
{route.duration}
</div>
<div className="text-[11px] text-gray-400 leading-tight">
{route.distance}
</div>
</div>
</button>
))}
</div>
</div>
);
}