Работа с данными и событиями модели мультимаршрута

Open in CodeSandbox

В данном примере для модели добавленного на карту мультимаршрута мы создаем еще одно пользовательское отображение. Данное отображение выводит краткое текстовое описание мультимаршурта и реагирует на изменение состояния модели. Пример иллюстрирует работу с событиями и данными модели мультимаршрута.

<!DOCTYPE html>
<html>
    <head>
        <title>Работа с данными и событиями модели мультимаршрута</title>
        <meta
            http-equiv="Content-Type"
            content="text/html; charset=utf-8"
        />
        <script
            src="https://yandex.st/jquery/2.2.3/jquery.min.js"
            type="text/javascript"
        ></script>
        <!--
        Укажите свой API-ключ. Тестовый ключ НЕ БУДЕТ работать на других сайтах.
        Получить ключ можно в Кабинете разработчика: https://developer.tech.yandex.ru/keys/
    -->
        <script
            src="https://api-maps.yandex.ru/2.1/?lang=ru_RU&amp;apikey=<ваш API-ключ>"
            type="text/javascript"
        ></script>
        <script src="custom_view.js" type="text/javascript"></script>
        <script
            src="multiroute_data_access.js"
            type="text/javascript"
        ></script>
        <style>
            html,
            body {
                width: 100%;
                height: 100%;
                padding: 0;
                margin: 0;
            }

            #map {
                width: 95%;
                height: 50%;
            }
            #viewContainer {
                margin: 8px;
            }
        </style>
    </head>

    <body>
        <div id="map"></div>
        <div id="viewContainer"></div>
    </body>
</html>
ymaps.modules.define(
    "MultiRouteCustomView",
    ["util.defineClass"],
    function (provide, defineClass) {
        // Класс простого текстового отображения модели мультимаршрута.
        function CustomView(multiRouteModel) {
            this.multiRouteModel = multiRouteModel;
            // Объявляем начальное состояние.
            this.state = "init";
            this.stateChangeEvent = null;
            // Элемент, в который будет выводиться текст.
            this.outputElement =
                $("<div></div>").appendTo("#viewContainer");

            this.rebuildOutput();

            // Подписываемся на события модели, чтобы
            // обновлять текстовое описание мультимаршрута.
            multiRouteModel.events.add(
                ["requestsuccess", "requestfail", "requestsend"],
                this.onModelStateChange,
                this
            );
        }

        // Таблица соответствия идентификатора состояния имени его обработчика.
        CustomView.stateProcessors = {
            init: "processInit",
            requestsend: "processRequestSend",
            requestsuccess: "processSuccessRequest",
            requestfail: "processFailRequest",
        };

        // Таблица соответствия типа маршрута имени его обработчика.
        CustomView.routeProcessors = {
            driving: "processDrivingRoute",
            masstransit: "processMasstransitRoute",
            pedestrian: "processPedestrianRoute",
        };

        defineClass(CustomView, {
            // Обработчик событий модели.
            onModelStateChange: function (e) {
                // Запоминаем состояние модели и перестраиваем текстовое описание.
                this.state = e.get("type");
                this.stateChangeEvent = e;
                this.rebuildOutput();
            },

            rebuildOutput: function () {
                // Берем из таблицы обработчик для текущего состояния и исполняем его.
                var processorName = CustomView.stateProcessors[this.state];
                this.outputElement.html(
                    this[processorName](
                        this.multiRouteModel,
                        this.stateChangeEvent
                    )
                );
            },

            processInit: function () {
                return "Инициализация ...";
            },

            processRequestSend: function () {
                return "Запрос данных ...";
            },

            processSuccessRequest: function (multiRouteModel, e) {
                var routes = multiRouteModel.getRoutes(),
                    result = ["Данные успешно получены."];
                if (routes.length) {
                    result.push("Всего маршрутов: " + routes.length + ".");
                    for (var i = 0, l = routes.length; i < l; i++) {
                        result.push(this.processRoute(i, routes[i]));
                    }
                } else {
                    result.push("Нет маршрутов.");
                }
                return result.join("<br/>");
            },

            processFailRequest: function (multiRouteModel, e) {
                return e.get("error").message;
            },

            processRoute: function (index, route) {
                // Берем из таблицы обработчик для данного типа маршрута и применяем его.
                var processorName =
                    CustomView.routeProcessors[
                        route.properties.get("type")
                    ];
                return index + 1 + ". " + this[processorName](route);
            },

            processDrivingRoute: function (route) {
                var result = ["Автомобильный маршрут."];
                result.push(this.createCommonRouteOutput(route));
                return result.join("<br/>");
            },

            processMasstransitRoute: function (route) {
                var result = ["Маршрут на общественном транспорте."];
                result.push(this.createCommonRouteOutput(route));
                result.push(
                    "Описание маршута: <ul>" +
                        this.createMasstransitRouteOutput(route) +
                        "</ul>"
                );
                return result.join("<br/>");
            },

            processPedestrianRoute: function (route) {
                var result = ["Пешеходный маршрут."];
                result.push(this.createCommonRouteOutput(route));
                return result.join("<br/>");
            },

            // Метод, формирующий общую часть описания для всех типов маршрутов.
            createCommonRouteOutput: function (route) {
                return (
                    "Протяженность маршрута: " +
                    route.properties.get("distance").text +
                    "<br/>" +
                    "Время в пути: " +
                    route.properties.get("duration").text
                );
            },

            // Метод, строящий список текстовых описаний для
            // всех сегментов маршрута на общественном транспорте.
            createMasstransitRouteOutput: function (route) {
                var result = [];
                for (var i = 0, l = route.getPaths().length; i < l; i++) {
                    var path = route.getPaths()[i];
                    for (
                        var j = 0, k = path.getSegments().length;
                        j < k;
                        j++
                    ) {
                        result.push(
                            "<li>" +
                                path
                                    .getSegments()
                                    [j].properties.get("text") +
                                "</li>"
                        );
                    }
                }
                return result.join("");
            },

            destroy: function () {
                this.outputElement.remove();
                this.multiRouteModel.events.remove(
                    ["requestsuccess", "requestfail", "requestsend"],
                    this.onModelStateChange,
                    this
                );
            },
        });

        provide(CustomView);
    }
);
function init() {
    // Создаем модель мультимаршрута.
    var multiRouteModel = new ymaps.multiRouter.MultiRouteModel(
            [[55.734876, 37.59308], "Москва, ул. Мясницкая"],
            {
                // Путевые точки можно перетаскивать.
                // Маршрут при этом будет перестраиваться.
                wayPointDraggable: true,
                boundsAutoApply: true,
            }
        ),
        // Создаём выпадающий список для выбора типа маршрута.
        routeTypeSelector = new ymaps.control.ListBox({
            data: {
                content: "Как добраться",
            },
            items: [
                new ymaps.control.ListBoxItem({
                    data: { content: "Авто" },
                    state: { selected: true },
                }),
                new ymaps.control.ListBoxItem({
                    data: { content: "Общественным транспортом" },
                }),
                new ymaps.control.ListBoxItem({
                    data: { content: "Пешком" },
                }),
            ],
            options: {
                itemSelectOnClick: false,
            },
        }),
        // Получаем прямые ссылки на пункты списка.
        autoRouteItem = routeTypeSelector.get(0),
        masstransitRouteItem = routeTypeSelector.get(1),
        pedestrianRouteItem = routeTypeSelector.get(2);

    // Подписываемся на события нажатия на пункты выпадающего списка.
    autoRouteItem.events.add("click", function (e) {
        changeRoutingMode("auto", e.get("target"));
    });
    masstransitRouteItem.events.add("click", function (e) {
        changeRoutingMode("masstransit", e.get("target"));
    });
    pedestrianRouteItem.events.add("click", function (e) {
        changeRoutingMode("pedestrian", e.get("target"));
    });

    ymaps.modules.require(
        ["MultiRouteCustomView"],
        function (MultiRouteCustomView) {
            // Создаем экземпляр текстового отображения модели мультимаршрута.
            // см. файл custom_view.js
            new MultiRouteCustomView(multiRouteModel);
        }
    );

    // Создаем карту с добавленной на нее кнопкой.
    var myMap = new ymaps.Map(
            "map",
            {
                center: [55.750625, 37.626],
                zoom: 7,
                controls: [routeTypeSelector],
            },
            {
                buttonMaxWidth: 300,
            }
        ),
        // Создаем на основе существующей модели мультимаршрут.
        multiRoute = new ymaps.multiRouter.MultiRoute(multiRouteModel, {
            // Путевые точки можно перетаскивать.
            // Маршрут при этом будет перестраиваться.
            wayPointDraggable: true,
            boundsAutoApply: true,
        });

    // Добавляем мультимаршрут на карту.
    myMap.geoObjects.add(multiRoute);

    function changeRoutingMode(routingMode, targetItem) {
        multiRouteModel.setParams({ routingMode: routingMode }, true);

        // Отменяем выбор элементов.
        autoRouteItem.deselect();
        masstransitRouteItem.deselect();
        pedestrianRouteItem.deselect();

        // Выбираем элемент и закрываем список.
        targetItem.select();
        routeTypeSelector.collapse();
    }
}

ymaps.ready(init);