как по клику обновить все метки, а выбранной дать другие параметры, сбросив предыдущий выбор

Я по клику отправляю запрос на сервер, в ответе получаю пункты выдачи заказов через курьерские службы. Дальше я эти пункты расставляю по карте, а под картой у меня список всех пунктов. Но суть не в этом.

По клику на метку я меняю у неё иконку. Всего у меня 4 службы, для каждой по 2 иконки (активна/неактивна). Если я выбираю первую метку, иконка меняется. Когда я кликаю на другую метку, иконка у первой не меняется обратно. Визуально получается на карте две пункта с иконками в состоянии active.

как мне по клику менять у предыдущей метки состоянии иконки до клика?

var pointsElement = $("#points").empty().show();
$(".btn-search-delivery").on("click", function() {
  var pointsElement = $("#points").empty();
  $.ajax({
    type: "POST",
    url: "https://site.ru/subscribe/delivery-methods",
    data: {
      "subscribe_form[category_id]": "13",
      "subscribe_form[first_catalog_id]": "76022",
      "subscribe_form[count_in_package]": "2",
      "subscribe_form[address_post_index]": "156000",
      "subscribe_form[address_country]": "Россия",
      "subscribe_form[address_region]": "Московская",
      "subscribe_form[address_city]": "Москва",
      "subscribe_form[payment_method]": "1"
    },
    dataType: "json",
    success: function(data) {
      var myMapAll = null;
      var clusterer = new ymaps.Clusterer({
        preset: 'islands#blueDotIcon',
        groupByCoordinates: false,
        clusterDisableClickZoom: false,
        gridSize: 40
      });
      var geoObjects = [];
      /** ymaps.ready function() **/
      ymaps.ready(function() {
        
        /** массив меток в списке **/
        $.each(data.pickupPoints, function(key, entry) {
          pointsElement.append($('<div class="col-12" id="pickup-item-' + entry.id + '"><label id="label' + entry.id + '" for="input' + entry.id + '" class="label-pickup-method"><input type="radio" name="pickup-method" id="input' + entry.id + '" value="' + entry.id + '"><div class="content-box"><div class="dot"></div><div class="title-box"><div class="title">' + entry.name + '<span class="price">' + entry.cost + ' ₽</span></div><div class="subtitle">' + entry.address + '</div></div><div class="select-box" data-dismiss="modal"><div class="select" aria-hidden="true">Выбрать</div></div></div></label></div>'))
        })
        /** ./массив меток в списке **/
        
        /** обработчик кликов по меткам в списке **/
        $(".pickup-method-box input[name=pickup-method]").change(function() {
          $(".label-pickup-method").removeClass("selected");
          $(this).parent().addClass("selected")
        })
        /** ./обработчик кликов по меткам в списке **/
        
        $("#map").empty();
        let geo_lat = $("input[name='subscribe_form[data_geo_lat]']").val()
        let geo_lon = $("input[name='subscribe_form[data_geo_lon]']").val()
        
        /** карта **/
        myMapAll = new ymaps.Map('map', {
          center: [geo_lat, geo_lon],
          zoom: 13
        }, {
          searchControlProvider: 'yandex#search'
        });
        /** ./карта **/
        
        /** массив меток на карте **/
        $.each(data.pickupPoints, function(i, v) {
          var placemark = new ymaps.Placemark([v.latitude, v.longitude], {
            hintContent: v.name + " &bull; " + v.address,
            id: v.id,
            deliveryServiceId: v.deliveryServiceId
          }, {
            iconLayout: 'default#image',
            iconLayoutColor: '#004FC5',
            iconImageHref: 'http://127.0.0.1:5500/img/modal/delivery/ya-' + v.deliveryServiceId + '.png',
            iconImageSize: [40, 40],
            iconImageOffset: [-20, -20]
          });
          placemark.events.add('click', clickOnPlacemark);
          geoObjects[i] = placemark;
          clusterer.add(geoObjects);
          myMapAll.geoObjects.add(clusterer);
        })
        /** ./массив меток на карте **/
        
        
        
        /** function clickOnPlacemark **/
        function clickOnPlacemark(e) {
          var target = e.get('target');
          var placemark = e.get('target');
          var id = placemark.properties.get('id');
          var deliveryServiceId = placemark.properties.get('deliveryServiceId');
          placemark.options.set({
            iconImageHref: 'http://127.0.0.1:5500/img/modal/delivery/ya-' + deliveryServiceId + '-pickup.png',
            iconImageSize: [40, 58],
            iconImageOffset: [-20, -38]
          })
          myMapAll.panTo(target.geometry.getCoordinates(), {useMapMargin: true});
          $("input[name=pickup-method]:checked").prop('checked', false);
          $(".label-pickup-method").removeClass("selected");
          $("#input" + id).prop('checked', true);
          $("#label" + id).addClass("selected");
          var $container = $('.pickup-method-box-wrap');
          var $scrollTo = $('#pickup-item-' + id);
          $container.animate({
            scrollTop: $scrollTo.offset().top - $container.offset().top + $container.scrollTop()
          })
        }
        /** ./function clickOnPlacemark **/
      })
       /** ./ymaps.ready function() **/
    }
  })
})


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

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

Описанную задачу можно решить с использованием менеджера объектов (https://tech.yandex.ru/maps/jsapi/doc/2.1/ref/reference/ObjectManager-docpage/ ).

Вот пример с тремя менеджерами (для каждого типа меток): https://jsfiddle.net/naivv/5dvf6ag2/

Также можно посмотреть на коллекции геообъектов (https://tech.yandex.ru/maps/jsapi/doc/2.1/ref/reference/GeoObjectCollection-docpage/ ), вот пример в песочнице: https://tech.yandex.ru/maps/jsbox/2.1/geo_object_collection

ymaps.ready(init);

function init() {
  var myMap = new ymaps.Map('map', {
      center: [55.76, 37.64],
      zoom: 10
    }, {
      searchControlProvider: 'yandex#search'
    }),

    // https://tech.yandex.ru/maps/jsapi/doc/2.1/ref/reference/ObjectManager-docpage/
    greenObjectManager = new ymaps.ObjectManager({
      // Чтобы метки начали кластеризоваться, выставляем опцию.
      clusterize: true,
      // ObjectManager принимает те же опции, что и кластеризатор.
      gridSize: 32,
      //clusterDisableClickZoom: true
    }),
    greenObjPreset = 'islands#greenIcon', // стиль метки по умолчанию

    blueObjectManager = new ymaps.ObjectManager({
      // Чтобы метки начали кластеризоваться, выставляем опцию.
      clusterize: true,
      // ObjectManager принимает те же опции, что и кластеризатор.
      gridSize: 32,
      //clusterDisableClickZoom: true
    }),
    blueObjPreset = 'islands#blueIcon', // стиль метки по умолчанию

    blackObjectManager = new ymaps.ObjectManager({
      // Чтобы метки начали кластеризоваться, выставляем опцию.
      clusterize: true,
      // ObjectManager принимает те же опции, что и кластеризатор.
      gridSize: 32,
      //clusterDisableClickZoom: true
    }),
    blackObjPreset = 'islands#blackIcon', // стиль метки по умолчанию

    selectedObjId, // id выделенного в данный момент объекта
    redObjPreset = 'islands#redDotIcon'; // стиль выделенной метки


  // Чтобы задать опции одиночным объектам и кластерам,
  // обратимся к дочерним коллекциям ObjectManager.
  greenObjectManager.objects.options.set({
    preset: greenObjPreset,
    hasBalloon: false // в данном примере мне балун не нужен
  });
  greenObjectManager.clusters.options.set('preset', 'islands#greenClusterIcons');
  myMap.geoObjects.add(greenObjectManager);

  blueObjectManager.objects.options.set({
    preset: blueObjPreset,
    hasBalloon: false // в данном примере мне балун не нужен
  });
  blueObjectManager.clusters.options.set('preset', 'islands#blueClusterIcons');
  myMap.geoObjects.add(blueObjectManager);

  blackObjectManager.objects.options.set({
    preset: blackObjPreset,
    hasBalloon: false // в данном примере мне балун не нужен
  });
  blackObjectManager.clusters.options.set('preset', 'islands#blackClusterIcons');
  myMap.geoObjects.add(blackObjectManager);


  // https://tech.yandex.ru/maps/jsapi/doc/2.1/ref/reference/objectManager.ObjectCollection-docpage/

  // Обработка события, возникающего при щелчке
  // левой кнопкой мыши на объекте
  greenObjectManager.objects.events.add('click', function(e) {
    //var target = e.get('target');
    var objectId = e.get('objectId');
    // ранее выделенной метке назначаем стиль по умолчанию
    if (selectedObjId) {
      greenObjectManager.objects.setObjectOptions(selectedObjId, {
        preset: greenObjPreset
      });
      blueObjectManager.objects.setObjectOptions(selectedObjId, {
        preset: blueObjPreset
      });
      blackObjectManager.objects.setObjectOptions(selectedObjId, {
        preset: blackObjPreset
      });
    }
    // подсвечиваем вновь выделенную метку
    greenObjectManager.objects.setObjectOptions(objectId, {
      preset: redObjPreset
    });
    selectedObjId = objectId;
  });
  blueObjectManager.objects.events.add('click', function(e) {
    var objectId = e.get('objectId');
    // ранее выделенной метке назначаем стиль по умолчанию
    if (selectedObjId) {
      greenObjectManager.objects.setObjectOptions(selectedObjId, {
        preset: greenObjPreset
      });
      blueObjectManager.objects.setObjectOptions(selectedObjId, {
        preset: blueObjPreset
      });
      blackObjectManager.objects.setObjectOptions(selectedObjId, {
        preset: blackObjPreset
      });
    }
    // подсвечиваем вновь выделенную метку
    blueObjectManager.objects.setObjectOptions(objectId, {
      preset: redObjPreset
    });
    selectedObjId = objectId;
  });
  blackObjectManager.objects.events.add('click', function(e) {
    var objectId = e.get('objectId');
    // ранее выделенной метке назначаем стиль по умолчанию
    if (selectedObjId) {
      greenObjectManager.objects.setObjectOptions(selectedObjId, {
        preset: greenObjPreset
      });
      blueObjectManager.objects.setObjectOptions(selectedObjId, {
        preset: blueObjPreset
      });
      blackObjectManager.objects.setObjectOptions(selectedObjId, {
        preset: blackObjPreset
      });
    }
    // подсвечиваем вновь выделенную метку
    blackObjectManager.objects.setObjectOptions(objectId, {
      preset: redObjPreset
    });
    selectedObjId = objectId;
  });

  $.ajax({
    url: "https://api.myjson.com/bins/77e60"
  }).done(function(data) {
    greenObjectManager.add(data);
  });
  $.ajax({
    url: "https://api.myjson.com/bins/125xmg"
  }).done(function(data) {
    blueObjectManager.add(data);
  });
  $.ajax({
    url: "https://api.myjson.com/bins/12rd88"
  }).done(function(data) {
    blackObjectManager.add(data);
  });

}

// https://tech.yandex.ru/maps/jsbox/2.1/geo_object_collection
<!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=<ваш API-ключ>" type="text/javascript"></script>
  <script src="https://yandex.st/jquery/2.2.3/jquery.min.js" type="text/javascript"></script>
  <style>
    html,
    body,
    #map {
      width: 100%;
      height: 100%;
      padding: 0;
      margin: 0;
    }
    
    a {
      color: #04b;
      /* Цвет ссылки */
      text-decoration: none;
      /* Убираем подчеркивание у ссылок */
    }
    
    a:visited {
      color: #04b;
      /* Цвет посещённой ссылки */
    }
    
    a:hover {
      color: #f50000;
      /* Цвет ссылки при наведении на нее курсора мыши */
    }
  </style>
</head>

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

</html>

→ Ссылка