Клуб API Карт

Масштабирование в зависимости от расположения меток.

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

Добрый день. Подскажите, пожалуйста, есть ли возможность масштабировать карту в зависимости от расположения меток на ней? То есть, если стоит одна метка в центре Москвы, то масштаб до "улицы", а если несколько меток от Сочи до Мурманска, то соответствующий мастаб, чтобы на карту были видны все метки.

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

Если метки в коллекции, то можно делать так.

1. Получаем границы области - collection.getBounds()

2. С помощью метода util.bounds.getCenterAndZoom получаем новые центр и зум карты

3. Проверяем - если метка одна, то обрезаем масштаб, чтобы он не был больше 17

4. Выставляем полученные значения карте map.setCenter(center, zoom)

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

А если метки не в коллекции ,а в группе, можно такое проделать?

А чем группа отличается от коллекции?

Раз вы спрашиваете, значит ничем ). Подскажите еще, пожалуйста. Добавил все в коллекцию, вывожу на карту: 

myMap.geoObjects.add(myCollection);

myMap.setBounds(myCollection.getBounds()); 

Но не могу разобраться с синтаксисом util.bounds.getCenterAndZoom . Как мне его использовать в своей коллекции?

var centerAndZoom = ymaps.util.bounds.getCenterAndZoom(

    myCollection.getBounds(),

    myMap.container.getSize(),

    myMap.options.get('projection')

);

А не подскажите пример использования util.bounds.getCenterAndZoom? В документации не нашел.

var centerAndZoom = ymaps.util.bounds.getCenterAndZoom(

    myMap.getBounds(),

    myMap.container.getSize(),

    myMap.options.get('projection')

);

    

Это я прочитал. Мне не понятно откуда взять данные для bounds. Нужно создать масив координат из коллекции и вычислить максимальную и минимальную? 

myCollection.getBounds()

Спасибо вам за подсказки. Все работает, но с масштабом проблемы. Если точек много и они разбросаны по карте, то все хорошо, но если точка одна, то масштабирует очень сильно и карты не видно. Мне советовала: Проверить - если метка одна, то обрезаем масштаб, чтобы он не был больше 17. 

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

1. Спросить у коллекции количесто элементов

2. Если элемент один, выставить карте центр и масштаб 17

Через checkZoomRange ?

Делаю так:

var geoObjectsLength = 0;
        yandexmap.geoObjects.each(function (geoObject) {
            geoObjectsLength++;
        });
        if(geoObjectsLength > 1) {
            var centerAndZoom = ymaps.util.bounds.getCenterAndZoom(yandexmap.geoObjects.getBounds(),
                yandexmap.container.getSize(),
                yandexmap.options.get('projection')
            );           
            console.log('centerAndZoom: '+centerAndZoom.center);
            console.log('centerAndZoom: '+centerAndZoom.zoom);
            yandexmap.setBounds(yandexmap.geoObjects.getBounds(), {
                    checkZoomRange: true,
                    zoomMargin: 100
                }
            );
        } else {
            yandexmap.setCenter(yandexmap.geoObjects.get(0).geometry.getCoordinates(), get('zoom', 0); ?>).panTo(yandexmap.getCenter());
        }

но увеличение, почему-то всегда возвращается как 0 и карта не прорисовывается.

Не могу понять в чем причина. Адрес странички - http://demo.raslab.org/vendor/admin

Видимо Ваш контейнер с картой не успевает получить размеры при переключении таба

yandexmap.container.getSize()[0, 0]

И не стоит вычислять длину yandexmap.geoObjects

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

 

Создайте свою коллекцию, добавьте ее в yandexmap.geoObjects и поместите в нее ваши метки.

Длину можно узнать с помощью ее метода getLength()

т.е. если сделать var size;
            jQuery.when(function() {
                size = yandexmap.container.getSize();
            }).then(function() {
                var centerAndZoom = ymaps.util.bounds.getCenterAndZoom(yandexmap.geoObjects.getBounds(), size, yandexmap.options.get('projection'));
                console.log('centerAndZoom: '+centerAndZoom.center);
                console.log('centerAndZoom: '+centerAndZoom.zoom);
            });

должно заработать? Сейчас проверю данный вариант.

 

у меня почему-то containerSize is undefined.

Я не понял зачем так делать и что это даст.

У Вас табы с помощью чего переключаются?

Если я создаю метки простым последовательным добавлением Placemark на карту:

myPlacemark = new ymaps.Placemark([ коорд х1], { content: 'текст', balloonContent: ' текст' });
     myMap.geoObjects.add(myPlacemark);
     myPlacemark = new ymaps.Placemark([коорд х2], { content: 'текст2', balloonContent: 'текст2' });
     myMap.geoObjects.add(myPlacemark);
итд

то описанный Вами метод будет работать?  (Цель та-же что и топикстартера- чтобы были видны все метки независимо от их расположения). И правильно ли вообще так добавлять метки? (Меток будет 20-25)

Лучше добавлять в отдельную коллекцию и ее уже в myMap.geoObjects

Можно вкраце пояснить что дасть коллекция, чем простое добавление меток? 

И  какую геоколлекцию  лучше  создавать упорядоченную или нет?  Вроде как в описании (http://api.yandex.ru/maps/doc/jsapi/2.x/dg/concepts/geoobjects.xml) рекомендуется неупорядоченные? И еще: подскажите как из

 

var centerAndZoom = ymaps.util.bounds.getCenterAndZoom(

    myCollection.getBounds(),

    myMap.container.getSize(),

    myMap.options.get('projection')

);

вытащить значения center и zoom  которые подставлять в map.setCenter(center, zoom)?

 

У коллекции есть метод getLegth и removeAll

в отличии от myMap.geoObjects.

 

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

 

getCenterAndZoom возвращает объект с полями center и zoom

странное дело выходит:  когда после создания коллекции,  делаю

myMap.setBounds(myCollection.getBounds());

то карта уже перемасштабируется как-надо. А когда после этой строки добавляю

// Получаем границы области
    var centerAndZoom = ymaps.util.bounds.getCenterAndZoom(
    myMap.getBounds(),
    myMap.container.getSize(),
    myMap.options.get('projection'));

    myMap.setCenter([centerAndZoom.center, centerAndZoom.zoom]);

то нет ни карты ни меток, а только серая подложка (тайлы кажется это называется).

Что-то здесь лишнее? ))

 

Тут написана глупость

myMap.setCenter([centerAndZoom.center, centerAndZoom.zoom]);

массив из центра и масштаба =)

походу- точно ))) скобки остались когда просто цифры подставлял- тренировался  как это вообще работает и так и оставил не обращая на них внимания  )  без них все работает. Хотя если работает и без установки setCenter() , то может ее и не писать?  )))

да, достаточно setBounds

Спасибо Вам за помощь!  Без Вас ничего бы у меня не получилось

после setBounds() не нужно проставлять центр и приближение.

 кусок кода для добавления массива меток, функция получает JSON данные по типу:

 

[{"name":"\u041f\u0430...","descr":"\u0412\u043e ...","img":"","lat":"55.610117","lng":"37.742411"}]

 

var myGroup = new ymaps.GeoObjectArray({}) ;
        $.each(JSONdata, function (indx, item) {
            myGroup.add(new ymaps.Placemark([item.lat, item.lng],
                {
                    title: item.name,
                    description: item.descr,
                    image: item.img,
                    hintContent: item.name
                }, {
                    iconLayout: myIconLayout,
                    balloonLayout: myBalloonLayout,
                    balloonShadow: false,
                    hideIconOnBalloonOpen: false
                }
            )) ;
        }) ;

 

 далее добавляем коллекцию на карту

 myMap.geoObjects.add(myGroup) ;

 

и выставляем центр и зум

 

myMap.setBounds(myGroup.getBounds(), {checkZoomRange: true}) ;

 

и все красиво

 

 

когда ставлю {checkZoomRange: true} -  то как раз зум не выставляется, а без него все ок