Map API Yandex 3: Подсказки при наведении на полигон

Нет, всё таки версия 3 еще сыровата для внедрения в прод. Ну или «лыжи не едут». Для решения простой задачи — отображение подсказки над полигоном, пришлось переписываться с тех поддержкой яндекса (и они даже ответили!, чем я безмерно удивлён). В результате родился скрипт, в котором требуется переопределение вызовов класса. Хм.. это определенно не то что хочется видеть для получения базовых вещей, которые в версии 2.1 работают «из коробки».

async function main() {
    await ymaps3.ready;
    ymaps3.import.registerCdn('https://cdn.jsdelivr.net/npm/{package}',['@yandex/ymaps3-hint@0.0.1']);
    const {YMap,YMapDefaultSchemeLayer,YMapFeature,YMapDefaultFeaturesLayer,YMapFeatureSource,YMapFeatureDataSource,YMapEntity} = ymaps3;
    const {YMapHint,YMapHintContext} = await ymaps3.import('@yandex/ymaps3-hint');


    map = new ymaps3.YMap(
        document.getElementById('app'),
        {location: 
            {
                center: [39.8491648, 59.2084992], 
                zoom: 9 
            },
            showScaleInCopyrights: false  //шкала масштаба рядом в логотипом
        }        
    );  
    

    const defaultScheme = new YMapDefaultSchemeLayer({});    // Добавляем рисованное изображение карты
    map.addChild(defaultScheme);

    const features = new YMapDefaultFeaturesLayer();
    map.addChild(features);

       
   //получаем список районов
    common.AjaxPost("index.php?r=site2/get-areas","").then(async areas_list=>{
        console.log("-прочитал список районов ",areas_list);
        if (areas_list.error==false){
            for (var i = 0; i < areas_list.result.length; i++) {                        
                await common.AjaxPost("areas/"+areas_list.result[i].poly_filename,"aa").then(res2=>{
                    console.log(areas_list.result[i].name);                    
                    res2=common.ReverseCoors(res2);
                    console.log(areas_list.result[i].poly_fill_color);
                    const polygon = new ymaps3.YMapFeature({
                        geometry: {
                            type: 'Polygon',
                            coordinates: res2
                        },
                        properties: {
                          hint: areas_list.result[i].name+" район"
                        },                        
                        style: {
                                stroke: [
                                    {
                                        color: '#196DFF99',
                                        dash: [5, 10],
                                        width: 3
                                        
                                    }
                                ],
                                fillOpacity: 0.2,
                                fill: "#"+areas_list.result[i].poly_fill_color
                            }
                    });
                    features.addChild(polygon);
                });                 
            };        
        };
    });    
    
      const hint = new YMapHint({
        layers: [features.layer],
        hint: object => object?.properties?.hint
      });
      map.addChild(hint);

      hint.addChild(
        new(
          class MyHint extends YMapEntity {
            _onAttach() {
                this._element =document.createElement('div');
                this._element.className ='hint';
                this._detachDom =ymaps3.useDomContext(this,this._element);
                this._watchContext(
                YMapHintContext,
                    () => {
                      const context =this._consumeContext(YMapHintContext);
                      this._element.textContent =(context?.hint || '');
                      console.log(this._element);
                    }, {
                      immediate: true
                    }
                  );
                }
            _onDetach() {this._detachDom();}
          }
        )()
      );

};    

window.map = null;            
main();

Yandex Map: отображение меток в зависимости от масштаба карты

Работал давече с плагином HeatMap для яндекс карт. Всё хорошо, но один нюанс — невозможно навесить эвент на клик по точке карты. Ну или не нашел как. Пришлось задействовать «финт ушами» — при достижении определенного приближения, принудительно отрисовывать поверх точек heatmap свои «кликабельные» точки. В результете родилось нечто подобное:

obj = data.result; 
                heatmap = new ymaps.Heatmap(obj, {
                    // Радиус влияния.
                    radius: 15,
                    // Нужно ли уменьшать пиксельный размер точек при уменьшении зума. False - не нужно.
                    dissipating: false,
                    // Прозрачность тепловой карты.
                    opacity: 0.8,
                    // Прозрачность у медианной по весу точки.
                    intensityOfMidpoint: 0.05,
                    // JSON описание градиента.
                    gradient: {
                           0.1: 'rgba(128, 255, 0, 0.7)',
                           0.2: 'rgba(255, 255, 0, 0.8)',
                           0.7: 'rgba(234, 72, 58, 0.9)',
                           0.9: 'rgba(162, 36, 25, 1)',
                           1.0: 'rgba(0, 0, 0, 1)'
                       }
                });
                heatmap.options.events.add('click', function (e) {   
                    console.log(e);
                    var objectId = e.get('objectId');    
                    //objectManager.objects.balloon.open(objectId);
                });                    
                heatmap.setMap(myMap); 

        
       
        
                myMap.events.add('boundschange', function () {
                    size = myMap.getZoom();
                    console.log(size);
                    if (size>15){
                        console.log("-- пора бы и нарисовать метки");
                        if (all_deleted==true){
                            console.log("--- рисуем метки");
                            // настройки кластеризакции
                            objectManager = new ymaps.ObjectManager({
                                clusterDisableClickZoom: true,
                                geoObjectOpenBalloonOnClick: true,
                                clusterize: false
                            }); //кластеризуем
                            objectManager=SetClusterProp(objectManager);     
                            myMap.geoObjects.add(objectManager);   
                            objectManager.add(obj);  
                            objectManager.objects.events.add('click', function (e) {   
                                console.log(e);
                                var objectId = e.get('objectId');    
                                objectManager.objects.balloon.open(objectId);
                            });                                        
                          all_deleted=false;  
                        };
                    } else {
                        if (all_deleted==false){
                            myMap.geoObjects.remove(myMap.geoObjects.get(myMap.geoObjects.getLength()-1));                          
                            all_deleted=true;  
                        };
                    };
                });
                

MapYandex API: получение расстояний между двумя координатами

Задача: получить расстояние от точки до точки по автомобильным дорогам

Решение: воспользуемся вызовом route:

ymaps.route([
                [data[i]["to_latlatitude"],data[i]["to_longitude"]],
                [data[i]["from_latlatitude"],data[i]["from_longitude"]]
            ], {
                mapStateAutoApply: true
            }).then(function (route) {
                console.log("Маршрут:");
                console.log(route);
                console.log(route.getLength());

            });     

Получение геокординат по адресу

Задача: получить координаты по известному адресу

Решение: воспользуемся API Яндекс.Карты по геокодированию. К сожалению бесплатная версия ограничена 1000 запросов в сутки. Но это обходимо возможностью «растягивать» во времени заполнение БД


            $address= urlencode($maddress->address);
            $rul="https://geocode-maps.yandex.ru/1.x/?geocode=".$address."&format=json&results=1&apikey=".$api_map;
            var_dump($rul);
            $ch = curl_init($rul);        
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); 
            $res_curl=json_decode(curl_exec($ch));            
            if ($res_curl!=null){
                if (isset($res_curl->response->GeoObjectCollection->featureMember[0]->GeoObject->Point->pos)){
                 $coors=$res_curl->response->GeoObjectCollection->featureMember[0]->GeoObject->Point->pos;     
                 $coors= explode(" ",$coors);
                 var_dump($coors);
                }              
            };            

JavaScript именованные массивы как набор записей

Обычно для этой цели используют конструкцию Map, однако лично мне  не нравится его синтаксис, когда для доступа необходимо использовать get /set. Поэтому я обычно использую создание объекта. Т.е. получается что-то вроде:

 




1 2