Клуб API Карт

Не работает геокодирование. Почему?

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

Есть веб-страница. По окончании ее загрузки отображается яндекс.карта в <div id="YMapsID">, координаты (широта и долгота) центра карты вводятся в скрытые поля формы. Затем пользователь должен ввести в текстовое поле с именем (name) и id="problem_address" адрес, который надо геокодировать (преобразовать в координаты) и отобразить на карте в виде перемещаемой метки (Placemark), а также записать широту и долготу в соответствующие скрытые поля формы. Я написал следующий код, но он почему-то выполняется не полностью (отображается карта, координаты центра карты записываются в скрытые поля формы, но по нажатию на кнопку на карте не появляется метка). Почему? Заранее прошу прощения за "простыню" кода!

 

<html>
<head>
    <script src="http://api-maps.yandex.ru/2.0-stable/?load=package.full&lang=ru-RU" type="text/javascript"></script>
    <script type="text/javascript">
var myMap;
function init() {
    var myMap = new ymaps.Map("YMapsID", {
        center: [ymaps.geolocation.latitude, ymaps.geolocation.longitude],
        zoom: 12,
        behaviors: ["default", "scrollZoom"]
    });
    myMap.controls
    // Кнопка изменения масштаба
    .add('zoomControl')
    // Список типов карты
    .add('typeSelector')
    // Стандартный набор кнопок
    .add('mapTools')
    // Линейка масштаба
    .add('scaleLine')
    //Передача начальных координат точки в соответствующие поля формы:
    var lat = document.getElementById('latitude');
    lat.setAttribute('value', ymaps.geolocation.latitude);
    var lon = document.getElementById('longitude');
    lon.setAttribute('value', ymaps.geolocation.longitude);
}
ymaps.ready(init);
function showPoint() {
    var addr = document.getElementById('problem_address').getAttribute('value');
    // Поиск координат адреса из переменной addr:
    ymaps.geocode(addr, {
        results: 1
    }).then(function (res) {
        // Выбираем первый результат геокодирования.
        var firstGeoObject = res.geoObjects.get(0);
        myMap.container.fitToViewport();
        attachReverseGeocode(myMap);
        var myPlacemark2 = new ymaps.Placemark(firstGeoObject.geometry.getCoordinates(), {}, {
            draggable: true, // метку можно перемещать,
            preset: "twirl#violetStretchyIcon"
        });
        myMap.geoObjects.add(myPlacemark2);
    }, function (err) {
        // Если геокодирование не удалось, сообщаем об ошибке.
        alert(err.message);
    });
    //если вместо ymaps.geocode(......).then(function (res){.....}, function (err){.....}) вставить
    //ymaps.geoQuery(ymaps.geocode(addr)).addToMap(myMap);
    //то метка тоже не появится :(
}
    </script>
</head>
<body>
    <form action="index.php" method="post" name="ZayavkaForm">
        <input type="hidden" id="latitude" name="problem_latitude" value="">
        <input type="hidden" id="longitude" name="problem_longitude" value="">Введите примерный адрес проблемы *:
        <br>
        <input type="text" id="problem_address" name="problem_address" value="Москва, ул. Тверская, 13" size="50" maxlength="100">
        <input type="button" name="addr2map" value="Отметить на карте" onclick="showPoint()">
        <br>
        <div id="YMapsID" style="width: 535px; height: 330px;"></div>
        <input type="submit" name="submit" value="Отправить">
    </form>
</body>
</html>

 

3 комментария

 

Заранее прошу прощения за "простыню" кода!

На будущее - в редакторе поста есть кнопка "врезка".

Сейчас я убрал ваш код за Вас.

 

Я написал следующий код, но он почему-то выполняется не полностью (отображается карта, координаты центра карты записываются в скрытые поля формы, но по нажатию на кнопку на карте не появляется метка). Почему?

Если Вы плохо знаете спецификацию DOM, то возможно лучше использовать чтото типа jQuery для манипуляций с ним.

В частности у DOM-элементов есть понятие аттрибутов (attributes) и полей (properties).

У инпута аттрибут value указывает на поле defaultValue и не изменяется динамически (при вводе пользователем), в отличии от поля value.

http://stackoverflow.com/questions/11973678/difference-between-element-value-and-element-getattributevalue

Спасибо большое!

Помогла замена .getAttribute('value') на .value .

А точка на карту не ставилась видимо из-за недоступности переменной, указывающей на карту, в функции обработки клика по кнопке.

Сделал так, чтобы в функции обработки клика по кнопке сначала удалялся средствами DOM старый div с картой, а затем создавался новый такой же div, в котором карта еще не существует, после чего в div'e создавалась новая карта и на ней ставилась точка.

 

Вот новый код формы (теперь div с картой вложен в span, который будет использоваться скриптом для удаления div'a с картой, как своего потомка):


                           
                           
                           
                           

                                 
                                       
                                 
                           

 

А вот так теперь выглядит функция, которая обрабатывает клик по кнопке с id="addr2map":

function showPoint() {
                var addr = document.getElementById('problem_address').value;
                
                // Поиск координат адреса:
                ymaps.geocode(
                    addr,
                    {}
                ).then(function (res)
                    {
                        var parent = document.getElementById('YMapCell');
                        var child = document.getElementById('YMapsID');
                        parent.removeChild(child);
                        
                        var div2 = document.createElement('div');
                        div2.setAttribute('id',"YMapsID");
                        div2.setAttribute('style',"width: 535px; height: 330px;");
                        parent.appendChild(div2);
                        
                        // Выбираем первый результат геокодирования.
                        var firstGeoObject = res.geoObjects.get(0),
                        myMap = new ymaps.Map("YMapsID", {
                            center: firstGeoObject.geometry.getCoordinates(),
                            zoom: 17,
                            behaviors: ["default", "scrollZoom"]
                        });
                    
                        myMap.controls
                            // Кнопка изменения масштаба
                            .add('zoomControl')
                            // Список типов карты
                            .add('typeSelector')
                            // Стандартный набор кнопок
                            .add('mapTools')
                            // Линейка масштаба
                            .add('scaleLine')
                        
                        //alert(firstGeoObject.geometry.getCoordinates());
                        
                        var myPlacemark2 = new ymaps.Placemark(
                            firstGeoObject.geometry.getCoordinates(),
                            {},
                            {
                                draggable: true, // метку можно перемещать,
                                preset: "twirl#violetStretchyIcon"
                            }
                        );
                        myMap.geoObjects.add(myPlacemark2);
                        
                        var coords = thisPlacemark.geometry.getCoordinates();
                        var lat = document.getElementById('latitude');
                        lat.setAttribute ('value', coords[0].toPrecision(8));
                        var lon = document.getElementById('longitude');
                        lon.setAttribute ('value', coords[1].toPrecision(8));
                        
                        myPlacemark2.events.add('dragend', function(e) {
                            // Получение ссылки на объект, который был передвинут.
                            var thisPlacemark = e.get('target');
                            // Определение координат метки
                            var coords = thisPlacemark.geometry.getCoordinates();
                            var lat = document.getElementById('latitude');
                            lat.setAttribute ('value', coords[0].toPrecision(8));
                            var lon = document.getElementById('longitude');
                            lon.setAttribute ('value', coords[1].toPrecision(8));    
                            // и вывод их при щелчке на метке
                            thisPlacemark.properties.set('balloonContent', coords);
                            //alert (coords[0].toPrecision(6));
                        });
                
                    },
                    function (err) {
                        // Если геокодирование не удалось, сообщаем об ошибке.
                        alert(err.message);
                    }
                );

 

Зачем удалять контейнер с картой, когда можно просто удалить старую метку?

Как минимум если делать так, то надо сначала отписать обработчик dragend и вызвать myMap.destroy();

Иначе память будет утекать при каждом поиске.

Мы делали подобный пример и делились им в блоге

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