Клуб API Карт

Отступ до края карты

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

Опыт работы с Yandex Map невелик, поэтому прошу помощи, пните в нужном направлении.

Есть необходимость центрировать карту по группе точек. Это без проблем.

// list - это список координат
var collection = new ymaps.GeoObjectCollection();
for(var p in list) {
var place = list[p];

collection.add(new ymaps.Placemark([place.lat, place.lng]));
}

map.geoObjects.add(collection);
map.setBounds(collection.getBounds());

Но смысл в том, что маркеры могут попадать под навигацию (зумирование) или очень близко к верхнему краю. Хотелось бы выставить отступы от края(что-ли) или определить расстояние маркера до края на карте, если он находится <20px от края, то делать зум -1


map.setZoom(map.getZoom() - 1);


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

Сейчас наверное самое простое решение - всегда уменьшать зум на 1. А в будущих релизах мы добавим опцию margin для метода setBounds, чтобы можно было задавать отступы от любого края видимой области карты.

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

Да, можно, алгоритм такой.

1. Получаем центр карты в глобальных пиксельных координатах map.getGlobalPixelCenter()

2. Получаем размер видимой области карты map.container.getSize()

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

4. Получаем глобальные пиксельные координаты метки через projection.toGlobalPixels

5. Сравниваем с координатами углов карты.

Вот как раз тема подходящая. Заодно и вопрос задам.

У меня аналогичная задача, я пытаюсь сделать "в лоб"

//listPoints - коллекция геообъектов

function set_bounds_offset(){
    var size=myMap.container.getSize(),
        map_bounds=myMap.getBounds(),
        bounds=listPoints.getBounds(),
        offsets=[50,50,50,50],//bottom,left,top,right
        x=(map_bounds[1][1]-map_bounds[0][1])/size[0],
        y=(map_bounds[1][0]-map_bounds[0][0])/size[1];
    return [[bounds[0][0]-offsets[0]*y,bounds[0][1]-offsets[1]*x],[bounds[1][0]+offsets[2]*y,bounds[1][1]+offsets[3]*x]];
};

myMap.setBounds(set_bounds_offset(),{precizeZoom:true});

Без {precizeZoom:true} получаются слишком большие отступы из за но зато гарантированно ничего не попадает под контролы расположенные по углам. С {precizeZoom:true} вообще метки выпадают за пределы видимости. Подскажите, пожалуйста, где у меня ошибка.

 

Вы какую-то разницу в градусах делите на пиксели и получаете ерунду

"Какая-то разница в градусах" - это ширина и высота видимой области в градусах, после деления на "пиксели", а точнее на соответствующие размеры той же видимой области в пикселях в x, y должно находиться сколько градусов у нас приходится на один пиксель(град/пиксель). Если такое рассуждение неверно - поясните пожалуйста, я не так давно начал заниматься JavaScript и картами, поэтому вполне могу чего-то не понимать.

 

Градусы на пиксели делить не имеет смысла.
Марина выше привела правильный алгоритм преобразования. Воспользуйтесь им.

"Градусы на пиксели делить не имеет смысла." Почему?

После того как я установил {avoidFractionalZoom:false} всё работает. Алгоритм Марины можно значительно упростить если использовать getPixelBounds() и map.projection.wgs84Mercator.fromGlobalPixels(globalPixelPoint, zoom). Так я тоже пробовал, результаты аналогичные. На данный момент проблема в этих двух методах заключается в том, что правильные оффсеты устанавливаются только в случае если не меняется зум. В случае если зум после setBounds() изменился смещения тоже изменяются.

в одном градусе может быть разное количество пикселей, в зависимости от широты
Градусы - угловая величина и может быть меньше нуля

"в одном градусе может быть разное количество пикселей, в зависимости от широты" - а так же в зависимости от зума. И больше скажу не может быть, а должно быть. В моём случае мы в общем-то получаем(ведь линейные размеры мы вычисляем по противоположным углам) усреднённую величину для текущего зума, и если нам не нужна абсолютная точность(ну вот кто будет мерить реально ли отступ 50 пикселей а не 49 или 51?) результат оказывается вполне приемлемым.

"Градусы - угловая величина и может быть меньше нуля" - если говорить конкретно о моей задаче, то меня интересует только Россия, и тут никаких отрицательных величин не будет. А в общем случае мой вариант и с отрицательными значениями тоже вполне себе работает.

Ну да ладно, в таком ключе этот спор ни к чему не приведёт.

Собственно у меня появился другой вопрос. Чисто математический, как посчитать какой коэффициент зума будет выставлен если мы знаем область которая будет передана в setBounds() и размер контейнера

про другой вопрос лучше создать отдельную  тему