Клуб API Карт

Как сделать координаты по клику (или метке)

Пост в архиве.

Никак не получается сделать нужное. Подскажите, пожалуйста, кто понимает в этом...

Процесс на сайте такой:

1. пользователь указывает в полях страну, регион, город, улицу, дом. и нажимает "далее"

2. при нажатии вызывается валидация формы (на js). Запускается функция, которая берет из всех полей и строит адрес. Этот адрес отправляет через http. Получает через json ответ в Яндекс.карты. Если координаты найдены, то они заносятся в скрытые поля формы.

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

 

По клику получилось, но не совсем то, что нужно :)

var coords = e.get('coordPosition');
myGeoObject = new ymaps.GeoObject({
    geometry: {
        type: "Point", // тип геометрии - точка
        coordinates: coords // координаты точки
    }
});
myMap.geoObjects.add(myGeoObject);

 

Этот код добавляет кучу меток при многократных кликах. Т.е. старая метка не удаляется. Как можно проверить, есть ли уже метка. Если есть, то удалить старую и поставить новую?

С перетаскиванием метки по карте вообще все плохо. Никак не могу разобраться.

На другом же сайте есть такое решение: клик по карте - ставится метка. При повторном - она удаляется и ставится новая. Но при этом появляется в углу карты кнопка, чтобы удалить метку с карты.

Цель: нужно занести в БД координаты объекта.

Вот такая вот проблема. Может есть более правильные решения данной задачи?

38 комментариев

Более правильно не создавать-удалять, а передвигать созданную метку.

Также можно посмотреть этот пример из песочницы

вроде как то, что нужно. Спасибо. Буду пробовать...

можете подсказать еще по поводу проверки правильности адреса: нунжо отправить адрес пользователя и получить координаты. Это нужно сделать через ajax, через get-метод. Правильно? Можете дать ссылку на пример кода?

И еще вопрос такой: как хранить координаты в БД? В одном поле, с типом VARCHAR? Если в разных, то как разнести по полям?

Пример кода там же в песочнице.

http://api.yandex.ru/maps/jsbox/direct_geocode

 

Способ хранения координат в БД зависит от того как Вы их будете использовать.

Ну и что за БД наверное тоже надо указать.

MySQL. Использовать для вывода на карте: кластеризация, вывод объектов по районам города.

В MySQL можно использовать spatial indexes для хранения геоданных

Не могу разобраться, как можно полученные данные разбить на переменные: город, улица, дом...

Функция getAddress выводит.

Пробую так: 

 

function getAddress(coords ) {
        myPlacemark.properties.set('iconContent', 'поиск...');
        ymaps.geocode(coords, {kind: 'house'}).then(function (res) {
            var firstGeoObject = res.geoObjects.get(0);

            myPlacemark.properties
                .set({
                    iconContent: firstGeoObject.properties.get('house'),
                    balloonContent: firstGeoObject.properties.get('text'),
                    //balloonContent: firstGeoObject.properties.get(request )
                })
        });
    }

console.log('Адресные данные: ', firstGeoObject.properties.get('metaDataProperty.GeocoderMetaData.AddressDetails'));

Спасибо. Потихоньку получается то, что нужно... возник еще вопрос.

В ООП (js) не очень хорошие знания. Подскажите, пожалуйста, как получить из AddressDetails объекта параметр, например, "LocalityName".

А также вопрос по номерам домов. В результате возвращаются такие номера,  2/6с3-4

такой дом уже не разделить на корпусы, строения, дроби?

Вы можете вписать полный путь до этого свойства в параметре метода properties.get, что я приводил выше

Теперь такая проблема:

Если пользователь ввел неправильный адрес, например, "Кострома, ываыва", то res.geoObjects.get(0) возвращает null.

Мне же нужно сделать так, чтобы карта открывалась не в Москве (центр по умолчанию), а брался хотя бы город.

Подскажите, пожалуйста...

Если ничего не нашлось, то откуда городу взяться?

надо сделать автокомплит в поле ввода адреса, как тут, например

http://ymapsapi.ya.ru/replies.xml?item_no=1631

вот и я думаю :)

на одном сайте работает так. Да и в картах если набрать "Кострома вфыаыфваыва"

то откроется карта с меткой на костроме.

http://maps.yandex.ru/?text=Россия, Кострома&sll=40.926418,57.767683&ll=40.926418,57.767683&spn=0.645447,0.190068&z=11&l=map

maps.yandex.ru не показателен. Там много есть чего нет в АПИ и вообще ни где.  Их поиск — совсем отдельный от АПИ сервис, это не просто геокодирование

Ну вот, например, medikateka.ru/poi/add/

Если добавить адрес фирмы "Кострома фыва фываыва", то откроется карта с меткой в городе Кострома.

Все это я к тому, что хотелось бы сделать для пользователя удобнее. Чтобы он мог поставить метку в своем городе и с него начинал поиск, а не с Москвы. Если координаты не найдены, нужно открыть его указанный город.

Это решается либо интерфейсно через выбор города с помощью select, либо через автокомплит.

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

Теперь же выдается все как надо. Но возникла другая проблема: метка на карте ставиться и координаты возрващаются всегда.

А как можно определить, если пользователь неправильно указал дом, например, на картах такого дома еще нет. В таком случае возвращаются координаты улицы города, без дома. Хотелось бы, чтобы в таком случае предлагалось пользователю указать вручную координаты дома, кликнув на карте.

Подскажите, пожалуйста, как такое условие можно сформировать?

для того чтобы это определить надо проверить значение поля precision в данных, возвращаемых геокодером

примерно так

if(res.geoObjects.get(0).properties.get('metaDataProperty.GeocoderMetaData.precision') != 'exact') {

...

}

спасибо.

А как решают такие задачи: возвращается адрес: улица, дом. Эти данные вставляю в поля формы. Пользователь указал, например, "Ленина, 35". Кликнул. А вернулось "Улица Ленина, 35". Как можно избавиться от слова "улица"?

В AddressDetails должно быть название улицы без слова "улица"

не получается найти. Только полное название в ThoroughfareName

понятно

тогда только вырезать  "улица ", либо использовать res.geoObjects.get(0).properties.get('name')

Подскажите, пожалуйста, еще по такому вопросу:

Карта была сформирована по нажатию на кнопке "отобразить карту". Взялись координаты или адрес из формы и открылась, например, в Москве.

Далее пользователь вводит новый адрес и жмет "отобразить карту".

Как правильно действовать? А можно как-то перевести область видимости карты в новые координаты (например, он ввел другой город, вручную же не будет карту прокручивать)? А не то, координаты получаются по новому адресу, а карта не меняется.

Но я делаю так: удаляю карту (destroy) и метку (=null), если она была, и снова создаю карту и метку. Так карта меняется...

Ище такой вопрос. Всегда ли нужно указывать центральные координаты при создании карты? Правильно ли будет так: получить координаты и сделать их центральными при создании карты. А потом еще и метку по этим координатам поставить?

Удалять и создавать карту заного не надо. Можно просто выставлять ей новый центр

спасибо.

Подскажите, пожалуйста, как изменить стиль метки?

Вот тут: http://api.yandex.ru/maps/jsbox/event_reverse_geocode

есть код:

 

// Если метка уже создана – просто передвигаем ее
        if(myPlacemark) {
            myPlacemark.geometry.setCoordinates(coords);
        }
        // Если нет – создаем.

Как сделать метке другой стиль, при условии, если она есть? Перед строкой myPlacemark.geometry.setCoordinates(coords);

Нужен стиль:

preset: 'twirl#nightStretchyIcon'

Надо выставить метке эту опцию

Очень непростая проблема, точнее, не знаю, получится ли ее описать...

При клике на "далее", происходит валидация поля координат (запускается одна основная функция). Если нет координат, то получаем адрес и на основе его получаем координаты. Далее их вставляем в поле и возвращаем результат функции - "return res_valid_coords = true".

В функции есть условия if-else. В самом начале задается переменная, равная res_valid_coords = false. В процессе выполнения функции это значение меняется.

Когда процесс выполнения функции доходит до получения координат по адресу:

 

ymaps.geocode( address , {
            results: 1
        }).then(function (res) {
// тут получаем координаты и вставляем их в поле
//далее меняем res_valid_coords = true
}

то функция начинает свое выполнение не дожидаясь окончания выполнения этого кода. А в этом коде как раз и идет получение координат, вставка их в поле формы и измненение res_valid_coords на значение "true". А функция же идет дальше, в конце своей работы она возвращает return res_valid_coords (а он был задан в самом начале, как false), а только потом выполняется работа по получению координат.

2-й вариант. Вставить return в конце if-else. То в таком случае при вызовые функции валидации, возвращается undefined - типа такой функции нет.

Я так понимаю, дело в асинхронности...

 

пробую так заменить код:

 

var result = ymaps.geoQuery( ymaps.geocode( addr_val , { results: 1 }) );
        if (!result.isReady()) {
            result.then(function () {
                //разные вычисления
        })
}

Пишет, что ymaps.geoQuery is not a function


Как можно заставить выполняться все по порядку?

Подскажите, пожалуйста, решение проблемы, над которой бьюсь уже несколько дней.

Ваша функция выполняет асинхронный запрос, а вы хотите чтобы она вернула значение в синхронном потоке.

вы можете возвращать ymaps.util.Promise

вместо значения res_valid_coords

я не профи в js... не понимаю о чем это вы

Нужно оставить все как есть (асинхронно), а только return заменить? Или какой правильный синтаксис будет?

в документации не получается ничего найти по данному вопросу.

Можно использовать promises

и возвращать result из вашей функции

Не помогло :(

а нет примера использования? А не то я не понимаю даже куда и как это использовать, конкретно в моем случае с получением координат по указанному адресу...

К сожалению в рамках этого клуба я не могу научить вас программировать на javascript

 

Прочитайте про интерфейс Promises

Вот приблизительная реализация

 

function getAddress(address) {

     var promise = new ymaps.util.Promise();

 

    ymaps.geocode(address)

       .then(function (res) {

           If(res.geoObjects.get(0)) {

                  promise.resolve(res.geoObjects.get(0).geometry.getCoordinates());

            }

            else {

                  promise.reject("didn't find");

            }

       });

        return promise;

}

 

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

getAddress("Москва").then(function (coords) {

    // тут работаем с координатами

});

теперь понятно... все работает... спасибо!

p.s. в интернете очень мало информации по promise

Думаю, что спрашивать лучше в этой же теме :)

У меня на сайте скрипт работает так:

указываю адрес, нажимаю "далее". Скрипт проверяет полное ли соответствие адреса. Если да, то все ок. Если неполное, то открывается карта и пользоатель может кликнуть на ней. При клике получаю координаты и меняю название улицы и дома.

Потом он снова нажимает "Далее". И снова проверка адреса. В этом случае сразу все ок, т.к. адрес взялся из карт.

Проблема в том, когда находиться несколько адресов, возвращается неполное соответствие. Например, вот такой адрес:

Россия, Ленинградская область, Санкт-Петербург, Звенигородская  9

По такому адресу открывается карта Всеволожского района, а не Питера, т.к при запросе установлено возвращать 1 объект:

 

get_coords_by_addr( 'Россия, Ленинградская область, Санкт-Петербург, Звенигородская  9' , {results: 1} ).then(function ( res ) { ...})

Подскажите, пожалуйста, как в таком случае можно получить координаты?

разве нет решения?

Возможно поможет установка опции boundedBy в геокодере относительно Питера

можно подробнее..? когда ее ставить?

Правильно:

 

  
ymaps.geocode('Россия, Ленинградская область, Санкт-Петербург, Звенигородская  9', {

        boundedBy: myMap.getBounds('Санкт-Петербург'),
         strictBounds: true,
        results: 1
    }).then(function (res) { ... }

})

 Так получается. Но когда делаю так:

 

 var promise = new ymaps.util.Promise();
ymaps.geocode( addr_val , { 
        boundedBy: myMap.getBounds('Санкт-Петербург'),
         strictBounds: true,
results: 1 } )
       .then(function (res) {
            var res_exact = new Array();
            if( res.geoObjects.get(0) ) {
                if( res.geoObjects.get(0).properties.get('metaDataProperty.GeocoderMetaData.precision') == 'exact' )  res_exact[0] = true;
                else res_exact[0] = false;
                res_exact[1] = res.geoObjects.get(0).geometry.getCoordinates();
                  promise.resolve( res_exact );
            }
            else {
                  promise.reject( false );
            }
       });
        return promise;

пишет, что myMap не найден

 

 

Т.е. получается так, что если указывать опцию boundedBy: myMap.getBounds(), то необходимо существование созданной карты.

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

 

А как можно получить координаты не создавая карту?

Алексей Лебедев
31 января 2023, 22:28
dimik,
Здоровья вам