маршрут к метке на карте

Не получается выстраивание маршрута к метке при её выборе на карте по примерам в песочнице. Помогите разобраться!!! Другой вопрос: как в балуне сделать адрес метки в виде кнопки для построения маршрута до этой метки от геолокации пользователя?

`

<script type="text/javascript">
 ymaps.ready(function () {
      var myMap = new ymaps.Map('map', {
            center: [59.935,30.416],
            zoom: 11,
            controls: ['zoomControl', 'typeSelector', 'routeButtonControl']
        }, {
            searchControlProvider: 'yandex#search'
        });

    /* var control = myMap.controls.get('routeButtonControl');

    // Зададим координаты пункта отправления с помощью геолокации.
    control.routePanel.geolocate('from');

    // Откроем панель для построения маршрутов.
    control.state.set('expanded', true); */

        // Создаём макет содержимого.
        MyIconContentLayout = ymaps.templateLayoutFactory.createClass(
            '<div style="color: #FFFFFF; font-weight: bold;">$[properties.iconContent]</div>'
        ),

        myPlacemark1 = new ymaps.Placemark([59.60,30.30], {
            hintContent: 'Тех. Центр &rdquo;Садовая&rdquo;',
            balloonContentHeader: "Тех. Центр &rdquo;Садовая&rdquo;",
            balloonContentBody: '<img src="images/icon.png" height="150" width="200"> <br/> ' +
            '<a href="tel:+7 (111) 123-45-67"><b>+7 (111) 123-45-67</b></a><br/>' +
            '<b>Санкт-Петербург, ул. Садовая 2</b><br/>',
            balloonContentFooter: "Ежедневно с 9:00 до 20:00",
        }, {
            // Опции.
            // Необходимо указать данный тип макета.
            iconLayout: 'default#image',
            // Своё изображение иконки метки.
            iconImageHref: 'images/icon.png',
            // Размеры метки.
            iconImageSize: [96, 61],
            // Смещение левого верхнего угла иконки относительно
            // её "ножки" (точки привязки).
            iconImageOffset: [-48, -61]
        }),
        myPlacemark2 = new ymaps.Placemark([59.80,30.40], {
            hintContent: 'Тех. Центр &rdquo;Б. Морская&rdquo;',
            balloonContentHeader: "Тех. Центр &rdquo;Б. Морская&rdquo;",
            balloonContentBody: '<img src="images/icon.png" height="150" width="200"> <br/> ' +
            '<a href="tel:+7 (111) 123-45-68"><b>+7 (111) 123-45-68</b></a><br/>' +
            '<b>Санкт-Петербург, ул. Б. Морская 11</b><br/>',
            balloonContentFooter: "Ежедневно с 9:00 до 20:00",
        }, {
            // Опции.
            // Необходимо указать данный тип макета.
            iconLayout: 'default#image',
            // Своё изображение иконки метки.
            iconImageHref: 'images/icon.png',
            // Размеры метки.
            iconImageSize: [96, 61],
            // Смещение левого верхнего угла иконки относительно
            // её "ножки" (точки привязки).
            iconImageOffset: [-48, -61]
        });

    myMap.geoObjects
        .add(myPlacemark1)
        .add(myPlacemark2);  
});
    </script>`

НО, как вишенка на торте... ... предполагаю, лучше сделать так, что бы: 1. балун сворачивался при открытии "Маршрутной панели", 2. где-то по траектории маршрута указывалось онлайн-продолжительность поездки и/или прибытия к выбранной метке 3. и в случае с мобильной версией необходимо предложение открытия/загрузки Яндекс.Навигатора, а не Яндекс.Карт. На этом я бы "Сказку о Золотой рыбке" завершил ТАКОЕ ВОЗМОЖНО???


Ответы (1 шт):

Автор решения: naivv

Примеры в песочнице:

Еще может быть полезным почитать про макеты и шаблоны: https://tech.yandex.ru/maps/jsapi/doc/2.1/dg/concepts/layouts-docpage/ https://tech.yandex.ru/maps/jsapi/doc/2.1/ref/reference/Template-docpage/

В итоге у меня получилось вот так: https://jsfiddle.net/naivv/0gvztauk/

Теперь балун с кнопкой сворачивается и выводится новый балун - с информацией о расстоянии и времени в пути.

Что касается вопроса о мобильной версии - кажется, это уже не совсем JS API. Полагаю, начинать нужно отсюда: https://yandex.ru/dev/yandex-apps-launch/maps/doc/concepts/About-docpage/ (есть ограничения: https://yandex.ru/dev/yandex-apps-launch/maps/doc/concepts/yandexmaps-commercial-use-docpage/ - лучше спросить у техподдержки).

ymaps.ready(init);

function init() {
  var myMap = new ymaps.Map('map', {
    center: [59.7, 30.4],
    zoom: 11,
    // Добавим панель маршрутизации.
    controls: ['zoomControl', 'typeSelector', 'routeButtonControl']
  }, {
    searchControlProvider: 'yandex#search'
  });

  var control = myMap.controls.get('routeButtonControl');

  // Создаём макет содержимого.
  MyIconContentLayout = ymaps.templateLayoutFactory.createClass(
    '<div style="color: #FFFFFF; font-weight: bold;">$[properties.iconContent]</div>'
  );

  // Создание макета содержимого балуна.
  // Макет создается с помощью фабрики макетов с помощью текстового шаблона.
  MyBalloonContentLayout = ymaps.templateLayoutFactory.createClass(
    // https://tech.yandex.ru/maps/jsapi/doc/2.1/ref/reference/Template-docpage/
    '<div style="margin: 10px;">' +
    '<h3>{{properties.balloonContentHeader|raw}}</h3>' +
    '<div class="popover-content">{{properties.balloonContentBody|raw}}</div>' +
    '<br />' +
    '<button id="counter-button"><b>{{properties.myAddr}}</b></button>' +
    '<br />' +
    '<h5>{{properties.balloonContentFooter}}</h5>' +
    '</div>', {

      // Переопределяем функцию build, чтобы при создании макета начинать
      // слушать событие click на кнопке-счетчике.
      build: function() {
        // Сначала вызываем метод build родительского класса.
        MyBalloonContentLayout.superclass.build.call(this);
        // А затем выполняем дополнительные действия.
        //console.log(this);
        $('#counter-button').bind('click', this.onCounterClick);
      },

      // Аналогично переопределяем функцию clear, чтобы снять
      // прослушивание клика при удалении макета с карты.
      clear: function() {
        // Выполняем действия в обратном порядке - сначала снимаем слушателя,
        // а потом вызываем метод clear родительского класса.
        //console.log(this);
        $('#counter-button').unbind('click', this.onCounterClick);
        MyBalloonContentLayout.superclass.clear.call(this);
      },

      onCounterClick: function() {
        //console.log($(this).text());
        routeTo($(this).text());
      }

    });

  // Создание метки со сложной фигурой активной области
  // https://tech.yandex.ru/maps/jsapi/doc/2.1/dg/concepts/layouts-docpage/
  var polygonLayout = ymaps.templateLayoutFactory.createClass('<div class="placemark_layout_container"><div class="polygon_layout">1</div></div>');


  function routeTo(to) {
    // https://tech.yandex.ru/maps/jsbox/2.1/geolocated_multiroute
    // Зададим координаты пункта отправления с помощью геолокации.
    control.routePanel.geolocate('from');
    // Откроем панель для построения маршрутов.
    control.state.set('expanded', true);
    // https://tech.yandex.ru/maps/jsapi/doc/2.1/ref/reference/control.RouteButton-docpage/
    control.routePanel.state.set({
      to: to
    });
    //закроем балун с кнопкой
    myMap.balloon.close();
    control.routePanel.getRouteAsync().then(function(route) {
      // Зададим максимально допустимое число маршрутов, возвращаемых мультимаршрутизатором.
      route.model.setParams({
        results: 1
      }, true);
      // Повесим обработчик на событие построения маршрута.
      route.model.events.add('requestsuccess', function() {
        var activeRoute = route.getActiveRoute();
        if (activeRoute) {
          // Получим протяженность маршрута.
          var length = route.getActiveRoute().properties.get("distance"),
            duration = route.getActiveRoute().properties.get("durationInTraffic");
          // Создадим макет содержимого балуна маршрута.
          balloonContentLayout = ymaps.templateLayoutFactory.createClass(
            '<span  style="font-weight: bold">Расстояние: ' + length.text + '.</span><br/>' +
            '<span style="font-style: italic">Время проезда пути с учетом пробок: ' + duration.text + '</span>');
          // Зададим этот макет для содержимого балуна.
          route.options.set('routeBalloonContentLayout', balloonContentLayout);
          // Откроем балун.
          activeRoute.balloon.open();
        }
      })
    })
  }

  var polygonPlacemark = new ymaps.Placemark(
    [59.693409, 30.433196], {
      hintContent: 'HTML метка сложной формы'
    }, {
      iconLayout: polygonLayout,
      // Описываем фигуру активной области "Полигон".
      iconShape: {
        type: 'Polygon',
        // Полигон описывается в виде трехмерного массива. Массив верхнего уровня содержит контуры полигона. 
        // Первый элемента массива - это внешний контур, а остальные - внутренние.
        coordinates: [
          // Описание внешнего контура полигона в виде массива координат.
          [
            [-28, -76],
            [28, -76],
            [28, -20],
            [12, -20],
            [0, -4],
            [-12, -20],
            [-28, -20]
          ]
          // , ... Описание внутренних контуров - пустых областей внутри внешнего.
        ]
      }
    }
  );
  // Подпишемся на событие клика
  polygonPlacemark.events.add('click', function(e) {
    // Получим ссылку на геообъект, по которому кликнул пользователь.
    var target = e.get('target');
    routeTo(target.geometry.getCoordinates());
  });

  var myPlacemark1 = new ymaps.Placemark([59.60, 30.30], {
      hintContent: 'Тех. Центр &rdquo;Садовая&rdquo;',
      myAddr: 'Санкт-Петербург, ул. Садовая 2',
      balloonContentHeader: "Тех. Центр &rdquo;Садовая&rdquo;",
      balloonContentBody: '<img src="https://sandbox.api.maps.yandex.net/examples/ru/2.1/balloon_html/img/cinema.jpg" height="150" width="200"> <br/> ' +
        '<a href="tel:+7 (111) 123-45-67"><b>+7 (111) 123-45-67</b></a><br/>' +
        '<b>Санкт-Петербург, ул. Садовая 2</b><br/>',
      balloonContentFooter: "Ежедневно с 9:00 до 20:00",
    }, {
      // Опции.
      balloonContentLayout: MyBalloonContentLayout,
      // Запретим замену обычного балуна на балун-панель.
      // Если не указывать эту опцию, на картах маленького размера откроется балун-панель.
      balloonPanelMaxMapArea: 0,
      // Не скрываем иконку при открытом балуне.
      hideIconOnBalloonOpen: false,
      // И дополнительно смещаем балун, для открытия над иконкой.
      balloonOffset: [0, -48],
      // Необходимо указать данный тип макета.
      iconLayout: 'default#image',
      // Своё изображение иконки метки.
      iconImageHref: 'https://sandbox.api.maps.yandex.net/examples/ru/2.1/icon_customImage/images/ball.png',
      // Размеры метки.
      iconImageSize: [48, 48],
      // Смещение левого верхнего угла иконки относительно
      // её "ножки" (точки привязки).
      iconImageOffset: [-24, -48]
    }),
    myPlacemark2 = new ymaps.Placemark([59.80, 30.40], {
      hintContent: 'Тех. Центр &rdquo;Б. Морская&rdquo;',
      myAddr: 'Санкт-Петербург, ул. Б. Морская 11',
      balloonContentHeader: "Тех. Центр &rdquo;Б. Морская&rdquo;",
      balloonContentBody: '<img src="https://sandbox.api.maps.yandex.net/examples/ru/2.1/balloon_html/img/cinema.jpg" height="150" width="200"> <br/> ' +
        '<a href="tel:+7 (111) 123-45-68"><b>+7 (111) 123-45-68</b></a><br/>' +
        '<b>Санкт-Петербург, ул. Б. Морская 11</b><br/>',
      balloonContentFooter: "Ежедневно с 9:00 до 20:00",
    }, {
      // Опции.
      balloonContentLayout: MyBalloonContentLayout,
      // Запретим замену обычного балуна на балун-панель.
      // Если не указывать эту опцию, на картах маленького размера откроется балун-панель.
      balloonPanelMaxMapArea: 0,
      // Не скрываем иконку при открытом балуне.
      hideIconOnBalloonOpen: false,
      // И дополнительно смещаем балун, для открытия над иконкой.
      balloonOffset: [0, -48],
      // Необходимо указать данный тип макета.
      // Необходимо указать данный тип макета.
      iconLayout: 'default#image',
      // Своё изображение иконки метки.
      iconImageHref: 'https://sandbox.api.maps.yandex.net/examples/ru/2.1/icon_customImage/images/ball.png',
      // Размеры метки.
      iconImageSize: [48, 48],
      // Смещение левого верхнего угла иконки относительно
      // её "ножки" (точки привязки).
      iconImageOffset: [-24, -48]
    });

  myMap.geoObjects
    .add(myPlacemark1)
    .add(myPlacemark2)
    .add(polygonPlacemark);

}
html,
body,
#map {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
}

.placemark_layout_container {
  position: relative;
  font-family: Georgia;
  font-size: 40px;
  text-align: center;
  font-weight: bold;
}


/* Макет метки с "хвостиком" */

.polygon_layout {
  position: relative;
  background: #ffffff;
  border: 4px solid #943A43;
  width: 50px;
  height: 50px;
  position: absolute;
  left: -28px;
  top: -76px;
  color: #943A43;
}

.polygon_layout:after,
.polygon_layout:before {
  top: 100%;
  left: 50%;
  border: solid transparent;
  content: " ";
  height: 0;
  width: 0;
  position: absolute;
}

.polygon_layout:after {
  border-top-color: #943A43;
  border-width: 10px;
  margin-left: -10px;
}

.polygon_layout:before {
  border-top-color: #943A43;
  border-width: 16px;
  margin-left: -16px;
}
<!DOCTYPE html>
<html>

<head>
  <title>Маршрут от местоположения пользователя</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <!--
        Укажите свой API-ключ. Тестовый ключ НЕ БУДЕТ работать на других сайтах.
        Получить ключ можно в Кабинете разработчика: https://developer.tech.yandex.ru/keys/
    -->
  <script src="https://api-maps.yandex.ru/2.1/?lang=ru_RU&amp;apikey=60445215-6d3a-4f88-87fe-8d52b72e5bc9" type="text/javascript"></script>
  <script src="https://yandex.st/jquery/2.2.3/jquery.min.js" type="text/javascript"></script>
  <style>

  </style>
</head>

<body>
  <div id="map"></div>
</body>

</html>

→ Ссылка