Клуб API Карт

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

SFAIRAT-L
26 июня 2011, 17:23

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

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

Вот код, где в массив заносится все необходимая инфа из таблицы. В зависимости от значения в поле category, все метки получают соотвествующий цвет. Таким образом я попытался добится подобия рзбиения всех меток на группы. Если если возможность скрывать метки определенных цветов, тогда пожалуй задача была бы решена или же как иначе разбить все метки на группы? Подскажите пожалуйста!


//-----
$script = '';
$script='var data = [';
$query = 'SELECT `address`,`id`,`city`,`category` FROM `company` ORDER BY id';
$result = mysql_query($query) or die(mysql_error()) ;
while(true){
if (($row = mysql_fetch_array($result))==false) {break;};
 $query1 = 'SELECT `name` FROM `cities` WHERE id='.$row[2].'';
 $result1 = mysql_query($query1) or die(mysql_error()) ;
 $row1 = mysql_fetch_array($result1);
 $script.='{request:"'.$row1[0].','.$row[0].'",name:"<a href=http://site.ru.php?id='.$row[1].'>Подробнее</a>",';
if ($row[3]==1) {
        $script.='style: {parentStyle: "default#redPoint",  
                 balloonContentStyle: {
                 template: new YMaps.Template("<div>$[text]</div><br>$[name]")
                }}';
                }
elseif ($row[3]==2) {
        $script.='style: {parentStyle: "default#greenPoint",  
                 balloonContentStyle: {
                 template: new YMaps.Template("<div>$[text]</div><br>$[name]")
                }}';
                }
elseif ($row[3]==3) {
        $script.='style: {parentStyle: "default#bluePoint",  
                 balloonContentStyle: {
                 template: new YMaps.Template("<div>$[text]</div><br>$[name]")
                }}';
                }
$script.='},';}
$script.='""];';

//-----

Вот основной код:

//-----

    <script type="text/javascript">
        // Создание обработчика для события window.onLoad
        YMaps.jQuery(function () {
            // Создание экземпляра карты и его привязка к созданному контейнеру
            var map = new YMaps.Map(YMaps.jQuery("#YMapsID")[0]

            // Установка для карты ее центра и масштаба
            map.setCenter(new YMaps.GeoPoint(37.64, 55.76), 4);
            map.addControl(new YMaps.Zoom()
            map.enableScrollZoom(
            map.addControl(new YMaps.SearchControl()
            map.addControl(new YMaps.TypeControl([YMaps.MapType.MAP, YMaps.MapType.SATELLITE, YMaps.MapType.HYBRID], [1,2,3])
            // Координаты или адреса географических объектов
            <?php echo($script); ?>

            var geocoder = new MultiplyGeocoder(data);
            geocoder.setStyle({ balloonContentStyle : { template : new YMaps.Template("<div>$[text]</div>") } }
            map.addOverlay(geocoder);

            YMaps.Events.observe(geocoder, "Load", function (geocoder) {
                alert("Загрузка адресов завершена");
            }
        }

        // Реализует наследование прототипа без исполнения конструктора родителя
            function extend (child, parent) {
            var c = function () {};
            c.prototype = parent.prototype;
            c.prototype.constructor = parent;
            return child.prototype = new c;
        };

        // Множественный геокодер
        // requests - массив адресов
       function MultiplyGeocoder (requests) {
    YMaps.GeoObjectCollection.call(this);

    var _this = this,
        geocodeCallCount = 0,
        listeners = [];

    for (var i = 0, l = requests.length; i < l; i++) {
        geocode(requests[i]
    }

    function geocode (data) {
        var geocoder = new YMaps.Geocoder(data.request);

        geocodeCallCount++;

        listeners = listeners.concat(
            YMaps.Events.observe(geocoder, [geocoder.Events.Load, geocoder.Events.Fault], function (geocoder) {
                if (geocoder.length()) {
                    var geocodeResult = geocoder.get(0);
                    geocodeResult.name = data.name;
                    geocodeResult.setStyle(data.style);
                    _this.add(geocodeResult);
                }
                geocodeCallCount--;
                isFinish(
            })
       
    }

    function isFinish () {
        if (!geocodeCallCount) {
            YMaps.Events.notify(_this, "Load", _this);

            for (var i = 0, l = listeners.length; i < l; i++) {
                listeners[i].cleanup(
            }
        }
    }
}

var ptp = YMaps.Utils.extend(MultiplyGeocoder, YMaps.GeoObjectCollection);
    </script>

 

 

11 комментариев
Подписаться на комментарии к посту

Лучше хранить координаты тоже в базе,

чтобы не геокодировать каждый раз одни и теже адреса на клиенте.

Про группировку меток можно прочитать в документации

 

К сожалению пока приходится использовать именно такой вариант.
А насчет документации, то конкретно в том примере все понятно, но вот как использовать это в данном случае увы не могу придумать.
Подскажите пожалуйста решение, если это возможно в данном случае!

добавляете результаты геокодирования в разные группы

каждой группе назначаете свой стиль

 

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

возможно в этом цикле

for (var i = 0, l = requests.length; i < l; i++) {
        geocode(requests[i]);
    }

надо добавить условие, так чтобы результат функциии geocode(requests[i]); сразу записывался в разные группы? не могли бы вы привести хотя бы общий пример!

записывайте в data не просто массив адресов,

а, например, массив объектов,

у каждого объекта - поля адрес и стиль

 

Так а я разве не так же сделал?

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

$script='var data = [';
$query = 'SELECT `address`,`id`,`city`,`category` FROM `company` ORDER BY id';
$result = mysql_query($query) or die(mysql_error()) ;
while(true){
if (($row = mysql_fetch_array($result))==false) {break;};
 $query1 = 'SELECT `name` FROM `cities` WHERE id='.$row[2].'';
 $result1 = mysql_query($query1) or die(mysql_error()) ;
 $row1 = mysql_fetch_array($result1);
 $script.='{request:"'.$ro


w1[0].','.$row[0].'",name:"http://site.ru.php?id='.$row[1].'>Подробнее",';
if ($row[3]==1) {
        $script.='style: {parentStyle: "default#redPoint", 
                 balloonContentStyle: {
                 template: new YMaps.Template("$[text]
$[name]")
                }}';
                }
elseif ($row[3]==2) {
        $script.='style: {parentStyle: "default#greenPoint", 
                 balloonContentStyle: {
                 template: new YMaps.Template("$[text]
$[name]")
                }}';
                }
elseif ($row[3]==3) {
        $script.='style: {parentStyle: "default#bluePoint", 
                 balloonContentStyle: {
                 template: new YMaps.Template("$[text]
$[name]")
                }}';
                }
$script.='},';}
$script.='""];';

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


Пытался сделать на основе примера http://api.yandex.ru/maps/ymapsml/examples/menufromymapsml.html , но там несколько другой случай

я если честно в этой php-каше ничего не могу разобрать

дайте ссылку на страницу

ужас конечно... так много точек, да еще и геокодировать на клиенте.

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

 

template: new YMaps.Template("$[text]
$[name]")

 

создайте все стили заранее в объекте

 

var template = new YMaps.Template("$[text]
$[name]");
var styles = {
    red: {
        parentStyle: "default#redPoint",
        balloonContentStyle: {template: template}
    },
     blue: {
        parentStyle: "default#bluePoint",
        balloonContentStyle: {template: template}
    },
...
}

 

и добавьте их в коллекцию стилей,

при этом создав объект с коллекциями по тем же ключам 

var collections = {}for (var style in styles) {    var name = 'user#' + style + 'Point';    YMaps.Styles.add(name, styles[style]);    collections[name] = new YMaps.GeoObjectCollection(name);}

в массиве data у каждого объекта должно быть

2 поля request и style

 

var data = [
{request: 'Москва', style: 'red'},
{request: 'Питер', style: 'blue'},
....
]

 

затем при геокодировании

добавляйте его результат (плэйсмарк) в объект collections

по ключу стиля

 

collections[data.style].add(geocoder.get(0));
затем вы сможете манипулировать этими коллекциями по ключам (добавлять удалять с карты) по какому-нибудь событию

 

огромное спасибо! будем думать и пробовать!

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

к сожалению мне некоторые нюансы неясны, поэтому видимо и не вышло.

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

Если не трудно взгляните еще раз на код и скажите что не так.

http://youhouse.ru/map/