YMapRouteControl

Класс YMapRouteControl — добавляет элемент управления на карту в виде панели маршрута. Также есть встроенная подсказка при вводе названия места, кнопки управления панелью и возможность указать маршрутную точку щелчком мыши на карте.

Примечание

Данный класс является компонентом пакета @yandex/ymaps3-default-ui-theme и предоставляет дополнительную функциональность в JS API, которая не входит в основное API.

Для подключения пакета воспользуйтесь инструкцией.

Пример использования

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
    <script crossorigin src="https://cdn.jsdelivr.net/npm/@babel/standalone@7/babel.min.js"></script>
    <!-- To make the map appear, you must add your apikey -->
    <script src="https://api-maps.yandex.ru/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></script>

    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="./common.ts"
    ></script>
    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="../variables.ts"
    ></script>
    <script data-plugins="transform-modules-umd" data-presets="typescript" type="text/babel">
      import type {BaseRouteResponse, LngLat, RouteOptions, YMapFeature} from '@yandex/ymaps3-types';
      import type {YMapDefaultMarker} from '@yandex/ymaps3-default-ui-theme';
      import {FROM_POINT_STYLE, LOCATION, MARGIN, PREVIEW_POINT_STYLE, TO_POINT_STYLE, getStroke} from '../variables';
      import {TRUCK_PARAMS} from './common';

      window.map = null;

      main();
      async function main() {
          // Waiting for all api elements to be loaded
          await ymaps3.ready;
          const {YMap, YMapDefaultSchemeLayer, YMapDefaultFeaturesLayer, YMapControls} = ymaps3;

          const {YMapRouteControl, YMapDefaultMarker} = await ymaps3.import('@yandex/ymaps3-default-ui-theme');

          map = new YMap(document.getElementById('app'), {location: LOCATION, margin: MARGIN}, [
              new YMapDefaultSchemeLayer({}),
              new YMapDefaultFeaturesLayer({})
          ]);

          const dragEndHandler = () => {
              routeControl.update({
                  waypoints: [
                      map.children.includes(fromPoint) ? fromPoint.coordinates : null,
                      map.children.includes(toPoint) ? toPoint.coordinates : null
                  ]
              });
          };

          const fromPoint: YMapDefaultMarker = new YMapDefaultMarker({
              coordinates: map.center as LngLat,
              onDragEnd: dragEndHandler,
              draggable: true,
              ...FROM_POINT_STYLE
          });
          const toPoint: YMapDefaultMarker = new YMapDefaultMarker({
              coordinates: map.center as LngLat,
              onDragEnd: dragEndHandler,
              draggable: true,
              ...TO_POINT_STYLE
          });
          let previewPoint: YMapDefaultMarker = new YMapDefaultMarker({
              coordinates: map.center as LngLat,
              ...PREVIEW_POINT_STYLE
          });

          let featuresOnMap: YMapFeature[] = [];

          const routeControl = new YMapRouteControl({
              truckParameters: TRUCK_PARAMS,
              waypoints: [map.center as LngLat, null],
              onBuildRouteError() {
                  featuresOnMap.forEach((f) => map.removeChild(f));
                  featuresOnMap = [];
              },
              onRouteResult(result, type) {
                  featuresOnMap.forEach((f) => map.removeChild(f));
                  featuresOnMap = getFeatures(result, type);
                  featuresOnMap.forEach((f) => map.addChild(f));
              },
              onUpdateWaypoints(waypoints) {
                  const [from, to] = waypoints;
                  if (from) {
                      const {coordinates} = from.geometry;
                      fromPoint.update({coordinates});
                      map.addChild(fromPoint);
                  } else {
                      map.removeChild(fromPoint);
                  }

                  if (to) {
                      const {coordinates} = to.geometry;
                      toPoint.update({coordinates});
                      map.addChild(toPoint);
                  } else {
                      map.removeChild(toPoint);
                  }
                  if (!to || !from) {
                      featuresOnMap.forEach((f) => map.removeChild(f));
                      featuresOnMap = [];
                  }
              },
              onMouseMoveOnMap(coordinates, index, lastCall) {
                  if (!lastCall) {
                      previewPoint.update({coordinates});

                      if (!map.children.includes(previewPoint)) {
                          map.addChild(previewPoint);
                      }
                  } else {
                      map.removeChild(previewPoint);
                  }
              }
          });

          map.addChild(new YMapControls({position: 'top left'}).addChild(routeControl));

          const getFeatures = (result: BaseRouteResponse, type: RouteOptions['type']): YMapFeature[] => {
              if (type !== 'transit') {
                  const {geometry} = result.toRoute();
                  return [new ymaps3.YMapFeature({geometry, style: {stroke: getStroke(type), simplificationRate: 0}})];
              }
              return result.toSteps().map(
                  (step) =>
                      new ymaps3.YMapFeature({
                          geometry: step.geometry,
                          style: {stroke: getStroke(step.properties.mode as RouteOptions['type']), simplificationRate: 0}
                      })
              );
          };
      }
    </script>

    <!-- prettier-ignore -->
    <style> html, body, #app { width: 100%; height: 100%; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; } .toolbar { position: absolute; z-index: 1000; top: 0; left: 0; display: flex; align-items: center; padding: 16px; } .toolbar a { padding: 16px; }  </style>
    <link rel="stylesheet" href="./common.css" />
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
    <script crossorigin src="https://cdn.jsdelivr.net/npm/react@17/umd/react.production.min.js"></script>
    <script crossorigin src="https://cdn.jsdelivr.net/npm/react-dom@17/umd/react-dom.production.min.js"></script>
    <script crossorigin src="https://cdn.jsdelivr.net/npm/@babel/standalone@7/babel.min.js"></script>
    <!-- To make the map appear, you must add your apikey -->
    <script src="https://api-maps.yandex.ru/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></script>

    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="./common.ts"
    ></script>
    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="../variables.ts"
    ></script>
    <script data-plugins="transform-modules-umd" data-presets="react, typescript" type="text/babel">
      import {BaseRouteResponse, LngLat, YMapLocationRequest, RouteOptions} from '@yandex/ymaps3-types';
      import {YMapRouteControlProps, WaypointsArray} from '@yandex/ymaps3-default-ui-theme';
      import {FROM_POINT_STYLE, LOCATION, MARGIN, PREVIEW_POINT_STYLE, TO_POINT_STYLE, getStroke} from '../variables';
      import {computeBoundsForPoints, TRUCK_PARAMS} from './common';

      window.map = null;

      main();
      async function main() {
          // For each object in the JS API, there is a React counterpart
          // To use the React version of the API, include the module @yandex/ymaps3-reactify
          const [ymaps3React] = await Promise.all([ymaps3.import('@yandex/ymaps3-reactify'), ymaps3.ready]);
          const reactify = ymaps3React.reactify.bindTo(React, ReactDOM);

          const {YMap, YMapDefaultSchemeLayer, YMapDefaultFeaturesLayer, YMapControls, YMapFeature} = reactify.module(ymaps3);
          const {YMapRouteControl, YMapDefaultMarker} = reactify.module(
              await ymaps3.import('@yandex/ymaps3-default-ui-theme')
          );

          ReactDOM.render(
              <React.StrictMode>
                  <App />
              </React.StrictMode>,
              document.getElementById('app')
          );

          function App() {
              const [routeType, setRouteType] = React.useState<RouteOptions['type']>('driving');
              const [routeResult, setRouteResult] = React.useState<BaseRouteResponse>();
              const [showFeature, setShowFeature] = React.useState(false);
              const [fromCoords, setFromCoords] = React.useState<LngLat | undefined>();
              const [toCoords, setToCoords] = React.useState<LngLat | undefined>();
              const [previewCoords, setPreviewCoords] = React.useState<LngLat | undefined>();
              const [waypoints, setWaypoints] = React.useState<[LngLat, LngLat]>([LOCATION.center, null]);

              const onRouteResult = React.useCallback((result: BaseRouteResponse, type: RouteOptions['type']) => {
                  setRouteType(type);
                  setRouteResult(result);
                  setShowFeature(true);
              }, []);

              const onUpdateWaypoints = React.useCallback((waypoints: WaypointsArray) => {
                  const [from, to] = waypoints;
                  setFromCoords(from?.geometry?.coordinates);
                  setToCoords(to?.geometry?.coordinates);

                  if (!from || !to) {
                      setShowFeature(false);
                  }
                  setPreviewCoords(undefined);
              }, []);

              const onBuildRouteError = React.useCallback(() => {
                  setShowFeature(false);
              }, []);

              const onMouseMoveOnMap = React.useCallback<YMapRouteControlProps['onMouseMoveOnMap']>(
                  (coordinates, index, lastCall) => {
                      setPreviewCoords(() => (lastCall ? undefined : coordinates));
                  },
                  []
              );

              const onDragEndHandler = React.useCallback(
                  (coordinates: LngLat, type: 'from' | 'to') => {
                      if (type === 'from') {
                          setFromCoords(coordinates);
                          setWaypoints([coordinates, toCoords]);
                      } else {
                          setToCoords(coordinates);
                          setWaypoints([fromCoords, coordinates]);
                      }
                  },
                  [fromCoords, toCoords]
              );

              const features = React.useMemo(() => {
                  if (!routeResult) {
                      return null;
                  }
                  if (routeType !== 'transit') {
                      const {geometry} = routeResult.toRoute();
                      return [
                          <YMapFeature geometry={geometry} style={{stroke: getStroke(routeType), simplificationRate: 0}} />
                      ];
                  }
                  return routeResult
                      .toSteps()
                      .map((step) => (
                          <YMapFeature
                              geometry={step.geometry}
                              style={{stroke: getStroke(step.properties.mode as RouteOptions['type']), simplificationRate: 0}}
                          />
                      ));
              }, [routeResult, routeType]);

              return (
                  <YMap location={reactify.useDefault(LOCATION)} margin={MARGIN} ref={(x) => (map = x)}>
                      <YMapDefaultSchemeLayer />
                      <YMapDefaultFeaturesLayer />
                      <YMapControls position="top left">
                          <YMapRouteControl
                              truckParameters={TRUCK_PARAMS}
                              waypoints={waypoints}
                              onRouteResult={onRouteResult}
                              onUpdateWaypoints={onUpdateWaypoints}
                              onBuildRouteError={onBuildRouteError}
                              onMouseMoveOnMap={onMouseMoveOnMap}
                          />
                      </YMapControls>

                      {showFeature && features}
                      {fromCoords !== undefined && (
                          <YMapDefaultMarker
                              coordinates={fromCoords}
                              draggable
                              onDragEnd={(coordinates) => onDragEndHandler(coordinates, 'from')}
                              {...FROM_POINT_STYLE}
                          />
                      )}
                      {toCoords !== undefined && (
                          <YMapDefaultMarker
                              coordinates={toCoords}
                              draggable
                              onDragEnd={(coordinates) => onDragEndHandler(coordinates, 'to')}
                              {...TO_POINT_STYLE}
                          />
                      )}
                      {previewCoords !== undefined && (
                          <YMapDefaultMarker coordinates={previewCoords} {...PREVIEW_POINT_STYLE} />
                      )}
                  </YMap>
              );
          }
      }
    </script>

    <!-- prettier-ignore -->
    <style> html, body, #app { width: 100%; height: 100%; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; } .toolbar { position: absolute; z-index: 1000; top: 0; left: 0; display: flex; align-items: center; padding: 16px; } .toolbar a { padding: 16px; }  </style>
    <link rel="stylesheet" href="./common.css" />
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
    <script crossorigin src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js"></script>
    <script crossorigin src="https://cdn.jsdelivr.net/npm/@babel/standalone@7/babel.min.js"></script>

    <script src="https://api-maps.yandex.ru/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></script>

    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="./common.ts"
    ></script>
    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="../variables.ts"
    ></script>
    <script data-plugins="transform-modules-umd" data-presets="typescript" type="text/babel">
      import {BaseRouteResponse, LngLat, YMapLocationRequest, RouteOptions} from '@yandex/ymaps3-types';
      import {YMapRouteControlProps, WaypointsArray} from '@yandex/ymaps3-default-ui-theme';
      import {FROM_POINT_STYLE, LOCATION, MARGIN, PREVIEW_POINT_STYLE, TO_POINT_STYLE, getStroke} from '../variables';
      import {TRUCK_PARAMS} from './common';

      window.map = null;

      main();
      async function main() {
          // For each object in the JS API, there is a Vue counterpart
          // To use the Vue version of the API, include the module @yandex/ymaps3-vuefy
          const [ymaps3Vue] = await Promise.all([ymaps3.import('@yandex/ymaps3-vuefy'), ymaps3.ready]);
          const vuefy = ymaps3Vue.vuefy.bindTo(Vue);

          const {YMap, YMapDefaultSchemeLayer, YMapDefaultFeaturesLayer, YMapControls, YMapFeature} = vuefy.module(ymaps3);

          const {YMapRouteControl, YMapDefaultMarker} = vuefy.module(await ymaps3.import('@yandex/ymaps3-default-ui-theme'));

          const app = Vue.createApp({
              components: {
                  YMap,
                  YMapDefaultSchemeLayer,
                  YMapDefaultFeaturesLayer,
                  YMapControls,
                  YMapFeature,
                  YMapRouteControl,
                  YMapDefaultMarker
              },
              setup() {
                  const location = Vue.ref<YMapLocationRequest>(LOCATION);
                  const routeType = Vue.ref<RouteOptions['type']>('driving');
                  const routeResult = Vue.shallowRef<BaseRouteResponse>();
                  const showFeature = Vue.ref(false);
                  const fromCoords = Vue.ref<LngLat | undefined>();
                  const toCoords = Vue.ref<LngLat | undefined>();
                  const previewCoords = Vue.ref<LngLat | undefined>();
                  const waypoints = Vue.ref<[LngLat, LngLat]>([LOCATION.center, null]);

                  const refMap = (ref: any) => {
                      window.map = ref?.entity;
                  };
                  const onRouteResult = (result: BaseRouteResponse, type: RouteOptions['type']) => {
                      routeType.value = type;
                      routeResult.value = result;
                      showFeature.value = true;
                  };
                  const onUpdateWaypoints = (waypoints: WaypointsArray) => {
                      const [from, to] = waypoints;
                      fromCoords.value = from?.geometry?.coordinates;
                      toCoords.value = to?.geometry?.coordinates;

                      if (!from || !to) {
                          showFeature.value = false;
                      }
                      previewCoords.value = undefined;
                  };
                  const onBuildRouteError = () => {
                      showFeature.value = false;
                  };
                  const onMouseMoveOnMap: YMapRouteControlProps['onMouseMoveOnMap'] = (coordinates, index, lastCall) => {
                      previewCoords.value = lastCall ? undefined : coordinates;
                  };
                  const onDragEndHandler = (coordinates: LngLat, type: 'from' | 'to') => {
                      if (type === 'from') {
                          waypoints.value = [coordinates, toCoords.value];
                      } else {
                          waypoints.value = [fromCoords.value, coordinates];
                      }
                  };
                  const features = Vue.computed(() => {
                      if (!routeResult) {
                          return null;
                      }
                      if (routeType.value !== 'transit') {
                          const {geometry} = routeResult.value.toRoute();
                          return [
                              {
                                  geometry,
                                  style: {stroke: getStroke(routeType.value), simplificationRate: 0}
                              }
                          ];
                      }
                      return routeResult.value.toSteps().map((step) => ({
                          geometry: step.geometry,
                          style: {
                              stroke: getStroke(step.properties.mode as RouteOptions['type']),
                              simplificationRate: 0
                          }
                      }));
                  });

                  return {
                      LOCATION,
                      MARGIN,
                      FROM_POINT_STYLE,
                      PREVIEW_POINT_STYLE,
                      TO_POINT_STYLE,
                      TRUCK_PARAMS,
                      location,
                      routeType,
                      routeResult,
                      showFeature,
                      fromCoords,
                      toCoords,
                      previewCoords,
                      waypoints,
                      features,
                      onRouteResult,
                      onUpdateWaypoints,
                      onBuildRouteError,
                      onMouseMoveOnMap,
                      onDragEndHandler,
                      refMap
                  };
              },
              template:
                  <YMap :location="location" :margin="MARGIN" :ref="refMap">
                      <YMapDefaultSchemeLayer />
                      <YMapDefaultFeaturesLayer />
                      <YMapControls position="top left">
                          <YMapRouteControl
                              :truckParameters="TRUCK_PARAMS"
                              :waypoints="waypoints"
                              :onRouteResult="onRouteResult"
                              :onUpdateWaypoints="onUpdateWaypoints"
                              :onBuildRouteError="onBuildRouteError"
                              :onMouseMoveOnMap="onMouseMoveOnMap" />
                      </YMapControls>
                      <template v-if="showFeature">
                          <YMapFeature v-for="feature in features"
                              :geometry="feature.geometry"
                              :style="feature.style" />
                      </template>
                      <YMapDefaultMarker
                          v-if="fromCoords !== undefined"
                          :coordinates="fromCoords"
                          draggable
                          :onDragEnd="(coordinates) => onDragEndHandler(coordinates, 'from')"
                          v-bind="FROM_POINT_STYLE" />
                      <YMapDefaultMarker
                          v-if="toCoords !== undefined"
                          :coordinates="toCoords"
                          draggable
                          :onDragEnd="(coordinates) => onDragEndHandler(coordinates, 'to')"
                          v-bind="TO_POINT_STYLE" />
                      <YMapDefaultMarker
                          v-if="previewCoords !== undefined"
                          :coordinates="previewCoords" v-bind="PREVIEW_POINT_STYLE" />

                  </YMap>
          });
          app.mount('#app');
      }
    </script>

    <!-- prettier-ignore -->
    <style> html, body, #app { width: 100%; height: 100%; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; } .toolbar { position: absolute; z-index: 1000; top: 0; left: 0; display: flex; align-items: center; padding: 16px; } .toolbar a { padding: 16px; }  </style>
    <link rel="stylesheet" href="./common.css" />
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>

Конструктор

new YMapRouteControl(props)

Параметры конструктора

Параметр

Тип

props

YMapRouteControlProps

Унаследовано от

YMapComplexEntity.constructor

Props

export type YMapRouteControlProps = {
    geolocationTextInput?: string;
    clearFieldsText?: string;
    changeOrderText?: string;
    availableTypes?: AvailableTypes[];
    truckParameters?: TruckParameters;
    waypoints?: [LngLat | null, LngLat | null];
    waypointsPlaceholders?: [string, string];
    autofocus?: boolean;
    search?: (args: CustomSearch) => Promise<SearchResponse> | SearchResponse;
    suggest?: (args: CustomSuggest) => Promise<SuggestResponse> | SuggestResponse;
    route?: (args: CustomRoute) => Promise<BaseRouteResponse[]> | BaseRouteResponse[];
    onMouseMoveOnMap?: (coordinates: LngLat, index: number, lastCall: boolean) => void;
    onUpdateWaypoints?: (waypoints: WaypointsArray) => void;
    onRouteResult?: (result: BaseRouteResponse, type: AvailableTypes) => void;
    onBuildRouteError?: () => void;
};

Параметры

Параметр

Описание

geolocationTextInput

Текст, который будет отображаться в поле ввода при выборе геолокации пользователя.

clearFieldsText

Текст кнопки сброса маршрута.

changeOrderText

Текст кнопки заказа на изменение маршрута.

availableTypes

Массив доступных типов маршрутов в панели маршрутизации (driving, transit, truck, walking).

truckParameters

Парамеры объекта для грузового автомобиля (только для type=truck).

waypoints

Массив с координатами путевых точек ([LngLat, LngLat]).

waypointsPlaceholders

Массив с плейсхолдерами для ввода путевых точек ([string, string]).

autofocus

Отметка о том, что первая введенная путевая точка должна быть в фокусе при открытии.

search

Функция, которая переопределяет функцию search. По умолчанию используется ymaps3.search.

suggest

Функция, которая переопределяет функцию suggest. По умолчанию используется ymaps3.suggest.

route

Функция, которая переопределяет функцию route. По умолчанию используется ymaps3.route.

onMouseMoveOnMap

Обратный вызов, который вызывается, когда пользователь выбирает путевую точку на карте. Его можно использовать для отображения маркера под курсором пользователя.

onUpdateWaypoints

Обратный вызов, который вызывается, когда пользователь изменяет путевые точки.

onRouteResult

Обратный вызов, который получает маршрут между путевыми точками.

onBuildRouteError

Обратный вызов, который вызывается, если маршрут не может быть задан (маршрут не найден или ошибка сервера).

Методы

update

update(changedProps): void

Параметр

Тип

Описание

changedProps

Partial<YMapRouteControlProps>

Новые значения props.

Возвращается

void

Унаследовано от

YMapComplexEntity.update