Клуб API Карт

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

vladax
12 октября 2010, 18:45

Здравствуйте.

Никогда не работал с API-картами. Владею PHP, MySQL, немного JavaScript.

Есть база объектов в MySQL с названиями объектов, их адресами и
географическими координатами (по одной ТОЛЬКО Москве порядка 5000).

Необходимо следующее.

 Указатель с крестиком всегда посередине карты .

Пользователь, выбирая свое место нахождения, крутит карту и вокруг этого указателя рисуется окружность.

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

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

Поэтому я себе представляю это прибл. так:

Где то на карте (лучше за её пределами) есть кнопка "Сохранить
координаты", рядом с которой бегут и координаты во время прокрутки
карты.

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

После нажатия, карта перестает быть интерактивной (не двигается больше),

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

Метки этих объектов также появляются в окружности.

При клике на эти метки, появляется балун с названием объекта и его адресом.

Карта эта рисуется таким образом, чтобы периметр окружности упирался в края карты, чтобы был виден весь диапазон.

Рядом с кнопкой "Сохранить координаты" находится кнопка типа "Отменить выбор, начать новый."

При нажатии на неё все начинается заново. Только карта подгружается с того места, где была поставлена метка.

Да и ещё..

На первоначальном этапе выводить район карты, соответствующий айпи пользователя.

Так будет удобнее. Не выводить же всем карту СНГ! - приблежать замучаешься.

Хотя пользователь с айпи Ростова-на-Дону может сидеть и в Краснодаре например.

Надо подумать ваще то))

В конце концов, при нажатии кнопки "Следующий шаг" выбранные координаты должны сохраняться в базе MySQL.

Вот такая вот задачка.

Реально это все?

Если кто то поможет реализовать, готов заплатить за это деньги.

Спасибо.
33 комментария
Подписаться на комментарии к посту
Описанная вами задачи вполне реализуема.

Может вместо кнопки "Сохранить координаты" лучше добавить кнопку в панель инструментов, например, "поиск объектов". Когда она активируется, то происходит превращение курсора в метку "я здесь", в противном случае карта работает в штатном режиме.

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

По поводу круга в клубе как раз было недавно обсуждение:
http://clubs.ya.ru/mapsapi/replies.xml?item_no=12774
Я вот не очень понял задачу, которую вы решаете.
Из текста мне показалось, что на самом деле задача найти 10 ближайших до пользователя объектов. Так?
Т.е. найдя 10 ближайших, потом можно определить расстояние до самого отдаленного, а это и будет радиус круга, который нужно нарисовать.

Расскажите подробнее, какую задачу в целом хотите решить?
если окружность рисовать после сохранения то
непонятно что меняется при перемещении карты
наверное эту окружность надо рисовать при окончании перемещения карты
DragEnd
А вообще я не очень понимаю зачем вам эта окружность?
с ней будет куча проблем.
у вас сайт стилизован под морской бой или подзорную трубу? :-)

ландо, ребята..  Бог с ней окружностью и всем остальным пока.
Дойдем потом и до этого. Начнем с простого.
Научите PLZ как сделать типо как в яндексе сервисе определения координат,
чтобы карта крутилась относительно крестика посередине,
только координаты прокручивались не на карте, а в инпутах формы ниже,
чтобы потом при ее сабмите, получить их методом пост?
Карта не крутиться, она перемещается.

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

Навесшивать обработчик на сабмит удобно с помощью YMaps.jQuery (документация на сайте jQuery)
А как получить координаты центра карты легко найти в документации.

PS. Лучьше использовать не форму, а ajax запросы (почитайте про них в документации к jQuery), пользователь скажет спасибо.
Начинаю врубаться. Задачу упростил. Научился отправлять в форму координаты по клику на карте.
Не пойму только как програмно при следующем клике на карте убрать предыдущую метку?


// Запускаем обработчик события
// При щелчке на карте ставим метку,
// значения координат указателя мыши
// отправляются в инпут формы
YMaps.Events.observe(map, map.Events.Click, function (map, mEvent) {
    // ставим метку
    var placemark = new YMaps.Placemark(mEvent.getGeoPoint());
    map.addOverlay(placemark);
    // Отправляем координаты ты в поле coordinates формы
    YMaps.jQuery("#coordinates").attr("value", placemark.getGeoPoint());
});


Пробовал в функции обработчика перед постановкой метки заюзать removeOverlay(); - не получается :-(
Вынесите объявления переменной placemark за пределы обработчика.

var placemark;
YMaps.Events.observe(map, map.Events.Click, function (map, mEvent) {
    if (placemark) {
        map.removeOverlay(placemark);
    }

    // ставим метку
    placemark = new YMaps.Placemark(mEvent.getGeoPoint());
    map.addOverlay(placemark);
    // Отправляем координаты ты в поле coordinates формы
    YMaps.jQuery("#coordinates").attr("value", placemark.getGeoPoint());
});

Если не жалко всех оверлеев, которые были добавлены на карту, то можно поступить очень жестко - воспользоваться методом removeAllOverlays() и удалить все оверлеи с карты =)
Спасибо. Точно! Я ж её внутри обработчика каждый раз объявляю)

С кликаньем по карте и получением координат разобрался с горем пополам)

Теперь с прокруткой карты относительно крестика по центру (как тут http://api.yandex.ru/maps/tools/getlonglat/)
1. Не знаю как разместить и зафиксировать этот самый указатель всегда по центру карты
2. При перемещении карты, координаты центра карты не хотят бежать в инпуте как в примере,
а фиксированно появляются только после отпускания кнопки мыши.
Делаю так:

YMaps.Events.observe(map, map.Events.BoundsChange, function (map, mEvent) {
   YMaps.jQuery("#coordinates").attr("value", map.getCenter());
});


Дайте пинка в нужном направлении PLZ )))
Чтобы при перемещении карты координаты также записывались в форму, вам необходимо слушать событие Move у карты.

YMaps.Events.observe(map, [map.Events.Move, map.Events.BoundsChange], function () {
    placemark.setGeoPoint(map.getCenter()); // А этот ответ на ваш первый вопрос =)
    YMaps.jQuery("#coordinates").attr("value", map.getCenter());
});
Спасибо по поводу события Move,
однако первый вопрос продолжает мучить) -
Как поместить свой нарисованный графический указатель в центр карты?
Строка placemark.setGeoPoint(map.getCenter()); в Вашем, Саша, коде
приводит к тому, что координаты в форму не записываются(
Строка placemark.setGeoPoint(map.getCenter()); в Вашем, Саша, коде
приводит к тому, что координаты в форму не записываются(

Это не про запись в форму, а про то

Как поместить свой нарисованный графический указатель в центр карты


Для создания своего значка метки прочитайте раздел Создание пользовательского значка метки

Для записи в поле формы Вам нужна следующая строчка из Сашиного кода

YMaps.jQuery("#coordinates").attr("value", map.getCenter());
или можно
YMaps.jQuery("#coordinates").val(map.getCenter());

Здесь подразумевается что у вас id поля, в которое надо добавлять коорлдинату равно "coordinates"
рекомендую почитать документацию по jQuery
Лунный программист, спасибо за ликбез по созданию меток и записи данных в форму, но с этим я давно разобрался самостоятельно, если вы почитаете ветку)
мне хотелось бы знать, как зафиксировать указатель в виде крестика по центру, чтобы при перемещении карты, он всегда оставался на месте.
Указатель в виде крестика и есть ваша кастомная метка.
Чтобы он оставался в центре карты нужно слушать события перемещения и ставить её (метку/крестик) в центр.
Всё это есть в коде.
Что именно у Вас не получается?
Если вам нужно неактивное перекрестие, то можно добавить как слой:
http://gregof.narod.ru/crosshair.html
если вы захотите чтоб оно реагировало на действия пользователяб напрнимер в него можно кликнуть, то смотрите в сторону IControl.

Дизайн за вами, по коду видно, что это просто html.


а можно и как предлагает Лунный програмист, создать метку, которую двигать в противоположную сторону движению карты.
Пример кода можно попросить у Саши, это он писал "Определение координат".
А дайте, пожалуйста, ссылку на страничку. Так мы решим вашу задачу быстрее.
А смысл? Я ж пока только тренируюсь)
Думаю обойдусь без всяких радиусов.
Вот сделал такой пример http://www.usaparts.ru/api/click.html
И такой http://www.usaparts.ru/api/krest.html
В последнем примере в центр карты нужно добавить крестик.
Не знаю как сделать именно это:


Чтобы он оставался в центре карты нужно слушать события перемещения и ставить её (метку/крестик) в центр.


Пока хочу закончить первый пример.
Потом буду думать какой способ регистрации окажется удобнее для пользователя.. 1-й или 2-й? ))
Создам небольшую фокус группу и устрою маленький опрос )))
На самом деле это не так сложно, как может показаться на первый взгляд.

// Метка, отмечающая центр карты
var centerPlacemark = new YMaps.Placemark(map.getCenter(), {
    style : {
        iconStyle : {
            href : "http://api.yandex.ru/i/maps/icons/center.gif",
            size : new YMaps.Point(16, 16),
            offset : new YMaps.Point(-8, -8)
        }       }, 
    interactive : YMaps.Interactivity.NONE});
map.addOverlay(centerPlacemark);

// Перемещение метки в центр при любом сдвиге карты
YMaps.Events.observe(map, [map.Events.Move, map.Events.BoundsChange], function () {
    centerPlacemark.setGeoPoint(map.getCenter());
});

Я у метки выставил опцию interactive в значение none, потому что нам не нужно, чтобы по этой метки можно было щелкнуть.

P. S. Крестик лучше свой использовать, а то вдруг мы его у себя переименуем =)
Спасибо большущее!)
Теперь всё понятно)
Ещё такой вопрос, если не сильно ещё вас подзаимел своим ламерством в JS)) -
Пытался на лету разнести долготу и широту по разным полям..
вставляю в обработчик:

var arr = new Array();
var arr=center_coords.split(',');
longitude = arr[0];
latitude = arr[1];
YMaps.jQuery("#longitude").attr("value", longitude);
YMaps.jQuery("#latitude").attr("value", latitude);

Значения в форму не передаются(
Более того, карта при перемещении начинает сходить с ума =))
При малейшем движении мышкой на ней
может уехать до самой Камчатки например)))
В чем тут дело? никак не пойму..
B-)
Если center_coords - это строка, то делайте так:

var center = center_coords.splilt(",");
YMaps.jQuery("#longitude").attr("value", center[0]);
YMaps.jQuery("#latitude").attr("value", center[1]);

Если center_coords - это объект класса YMaps.GeoPoint, то так:

YMaps.jQuery("#longitude").attr("value", center.getLng());
YMaps.jQuery("#latitude").attr("value", center.getLat());

Карта начинает сходить с ума, потому что у вас возникает javascript-ошибка (где-то в коде). Скорее всего, я думаю, что можно придумать много способов, чтобы "взбесить" карту))
Чо та не выходит каменный цветок =((
center_coords - это
var center_coords = map.getCenter();
А дайте ссылку на страничку, пожалуйста. Я посмотрю.
там закоменчены куски http://www.usaparts.ru/api/cross.html
Посмотрите еще раз мой комментарий и следуйте по инструкции "Если center_coords - это объект класса YMaps.GeoPoint...". Метод getCenter() возвращает именно геоточку.
все так.. спасибо.. тогда не понимаю почему center_coords передается в форму как строка?
При записи значения в атрибут ожидается строка, а вы передаете объект геоточку. У объекта геоточки неявным образом вызывается метод toString(), который преобразует объект в строку.

Метод toString() является стандартным методом в javascript. Его можно переопределить, что мы и сделали для геоточки. Для геоточки метод toString() вернет строку координат, разделенных запятыми.
Понятно. И последний вопрос.
Каким образом можно разместить форму на самой карте?
Так же, как и в у вас в примере?
Я сделал небольшой элемент управления. Вы можете поступить таким же образом или поместить форму в контейнер с картой и выставить ей z-index побольше, чтобы она вышла на передний план.

Но лучше все же сделать элемент управления. Вот пример.
Почитал про YMaps.IControl... чесслово! ничего не понял(
И пример создания польз. элемента управдения слишком сложный для новичка в YMaps(
Я вам предложил два варианта: через свой контрол (более правильный вариант) или просто div положить внутрь карты и вывести его повыше:


    моя форма

Используемые z-index'ы перечислены в статическом классе YMaps.ZIndex.
Просто див положить неинтересно)
Вот как положить через Ваш контрол - совсем другое дело!)
Как это сделать, я не понимаю(
YMaps.jQuery(function () {
    var map = new YMaps.Map(YMaps.jQuery("#YMapsID"));
    map.setCenter(new YMaps.GeoPoint(37.64, 55.76), 10);
    map.addControl(new MyForm());
})

function MyForm () {
    var form = YMaps.jQuery("моя форма").css({
        position : "absolute",
        zIndex : YMaps.ZIndex.CONTROL
    });

    this.onAddToMap = function (map, positon) {
        form.appendTo(map.getContainer());
    };

    this.onRemoveFromMap = function () {
        form.remove();
    }
}


Подскажите  плиз... Задача элементарная - на клик по карте ставим метку, потом её  таскаем по карте, а в окошке отображаются координаты...

// Событие однократное "метка по нажатию кнопкой на карте"
var myEventListener = YMaps.Events.observe(map, map.Events.Click, function (map, mEvent) {
        var placemark = new YMaps.Placemark(mEvent.getGeoPoint(),  {draggable: true});
        map.addOverlay(placemark);
        YMaps.jQuery("#point").attr("value", mEvent.getGeoPoint());
        myEventListener.cleanup();
    }, this);

Работает. создаёт метку, перетаскиваемую и отображает координаты.... но!


      YMaps.Events.observe(placemark,[placemark.Events.DragStart, placemark.Events.Drag, placemark.Events.DragEnd], function (placemark, mEvent) {
      YMaps.jQuery("#point").attr("value", mEvent.getGeoPoint());
      });

не работает ни под майонезом, ни под кетчунезом... :(