вторник, 10 января 2012 г.

Поэтапное описание создания карты Яндекс и объектов, хранящихся в БД. Управление объектами Яндекс.Карты и сохранение в БД.

Известная поисковая система Яндекс предоставляет широкий набор сервисов для веб-приложений. Одним из них является широко распространенные Яндекс.Карты.
Во время разработки одного из проектов - создания географического портала в городе Ногинске Московской области, столкнулись с проблемой хранения объектов в базе данных и выборке нужных объектов Яндекс.Карты по определенным условиям. В документации пример описан недостаточно полно, пройдясь по форумам и собрав всю нужную информацию, мы принялись за написание собственного плагина работы с Яндекс.Картой. При этом он разделялся на две составляющие: управление из административной части объектами, поиск и отображение из базы данных на самом сайте.

Здесь расположен рабочий сайт компании Медиа Плюс - поставщика рекламных поверхностей в Подмосковье, на котором были использованы описанные в статье методы.
Задача достаточно простая: есть набор каких-либо объектов, у которых разные ценовые характеристики и разные типы. Это объекты типа A, типа B, типа C с разными ценами.
Необходимо:
  1. Хранить в базе данных весь набор объектов Яндекс.Карты;
  2. Осуществлять управление объектами Яндекс.Карты: добавление, перетаскивание, поиск по адресу;
  3. Осуществлять выборку объектов из базы данных и отображение их на карте;
  4. Осуществлять фильтрацию и поиск нужных объектов на карте.
В данной статье я рассмотрю первую часть это "хранение объектов в базе данных, управление объектами Яндекс.Карты". Описание разобью на этапы.
  1. Подключение карты Яндекс по уникальному ключу, выдаваемому под определенный домен (в данном случае под домен artmp.ru). Вид строки подключения следующий:

    <script src="http://api-maps.yandex.ru/1.1/index.xml?key=AF798U4BAAAAndSxIAIAVYUmhCXK8liReJEZxtr7MEJaH5cAAAAAAAAAAACsRNpPaossoymsn0DpFcxyGIPysw==" type="text/javascript"></script>

    Блок, где будет размещаться карта выглядеть должен так :

    <div id="YMapsID" style="width:600px;height:400px"></div>
    <input type="text" class="inputForm" name="city" id="citytext" value="<?=$city?>">
    <input type="text" class="inputForm" name="street" id="streettext" value="<?=$street?>">
    <input type="text" class="inputForm" name="address" value="<?=$address?>">
    <input type="button" value="Найти на карте" id="findAddress">

    К контейнеру с картой добавлена кнопка и поля, которые позволят осуществлять быстрый поиск нужного адреса. Адрес задается в виде: Город, Улица, Дом или Здание или Корпус или Литер. Пример: Ногинск, ул. 3-го Интернационала, д.50А.
  2. Инициализация карты и назначение стилей:
    var map, mapStyle;   //объявляем переменные, которые будут использоваться по всему коду 
    YMaps.jQuery(function () { 
    // Создаем экземпляр карты Яндекс и назначаем его привязанным к ранее сделанному контейнеру с ID = YMapsID
    map = new YMaps.Map(YMaps.jQuery("#YMapsID")[0]);

    // Устанавливает начальные параметры отображения карты: центр карты и коэффициент масштабирования
    map.setCenter(new YMaps.GeoPoint(38.442343, 55.854032), 11);
     
    // Создает элемент масштабирования
    var zoomControl = new YMaps.Zoom({noTips: true});
    map.addControl(zoomControl);

    // Создает стиль. Если стиль не задан, то объекты будут отображаться стандартными метками Яндекс
    mapStyle = new YMaps.Style();

    // Создает стиль значка метки
    mapStyle.iconStyle = new YMaps.IconStyle();
    mapStyle.iconStyle.href = "/images/map/flag.png";
    mapStyle.iconStyle.size = new YMaps.Point(34, 44);
    mapStyle.iconStyle.offset = new YMaps.Point(-9, -29);

    mapStyle.iconStyle.shadow = new YMaps.IconShadowStyle();
    mapStyle.iconStyle.shadow.href = "/images/map/flag_shadow.png";
    mapStyle.iconStyle.shadow.size = new YMaps.Point(34, 44);
    mapStyle.iconStyle.shadow.offset = new YMaps.Point(-9, -29);

    })
  3. Код для обработки перетаскивания метки и фиксирования ее текущих координат:

    //Функция поиска по нажатию на кнопку  findAddress
    $('#findAddress').click(function () {
    showAddress($('#citytext').val()+', '+$('#streettext').val()+', '+$('#addresstext').val());
    })

    //Функция отслеживания перемещения точки
    function dragObj(YMapObj, placemark) {
    YMapObj.Events.observe(placemark, placemark.Events.Drag, function (obj) {
    current = obj.getGeoPoint().copy();
    $('#currentPointAddress').val(current); // Присваиваем инпуту координаты x данные, по завершению перемещения маркера на карте

    currentScale = map.getZoom();
    $('#currentPointScale').val(currentScale);  //Присваиваем инпуту масштаба текущее значение по завершению перемещения маркера на карте
    });

    // Обработчик события изменения масштаба карты YMapObj.Events.observe(map,map.Events.SmoothZoomEnd, function () {
    currentScale = map.getZoom();
    $('#currentPointScale').val(currentScale);
    });
    return false
    }

    // Функция для отображения результата геокодирования
    // Параметр value - адрес объекта для поиска
    function showAddress (value) {
    // Удаление предыдущего результата поиска
    map.removeOverlay(placemark);
    map.removeOverlay(geoResult);

    // Запуск процесса геокодирования
    var geocoder = new YMaps.Geocoder(value, {results: 1, boundedBy: map.getBounds()});

    //var placemark = new YMaps.Placemark(new YMaps.GeoPoint(tile1, tile2), {draggable: true, style: "default#buildingsIcon"});
    // Создание обработчика для успешного завершения геокодирования
    YMaps.Events.observe(geocoder, geocoder.Events.Load, function () {
    // Если объект был найден, то добавляем его на карту
    // и центрируем карту по области обзора найденного объекта
    if (this.length()) {
    geoResult = this.get(0);  //берется первый найденный объект. Для данной задачи этого достаточно
    placemark = new YMaps.Placemark(geoResult.getGeoPoint(), {draggable: true, style: mapStyle});
    map.addOverlay(placemark);
    map.setBounds(geoResult.getBounds());

    $('#currentPointAddress').val(geoResult.getGeoPoint());
    dragObj(YMaps, placemark);
    }else {
    alert("Ничего не найдено, введите полный адрес")
    }
    });

    // Обработка ошибок ответа геокодера. Процесс геокодирования завершен неудачно
    YMaps.Events.observe(geocoder, geocoder.Events.Fault, function (geocoder, error) {
    alert("Произошла ошибка: " + error);
    })
    }

  4. Последний этап - это сохранение данных в БД. Т.к. по результатам перемещения метки или изменения масштаба новые данные присваиваются соответствующим инпутам currentPointAddress и currentPointScale, то при сабмите формы и передаче запроса POST, мы просто обрабатываем эти параметры и сохраняем обычным способом.
В коде стоит обратить внимание на ответ геокодера geoResult = this.get(0); для нашей задачи этого вполне хватило, т.к. область поиска была ограничена одним городом и мы брали первое значение массива результатов.
Однако при больших масштабах найденных адресом может быть не один, а много и тогда целесообразно производить проход по циклу и выводить нужные для уточнения в каком-либо определенном поле или выпадающем списке.

Далее в следующей статье я приведу пример того, как производилась обработка хранящихся в базе данных объектов.

Комментариев нет:

Отправить комментарий