Клуб API Карт

Обновление карты

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

Есть собственный слой на я-карте с собственным источником тайлов. В ответе сервера с тайлами выставлены Expired и max-age. Все замечательно работает.

 

Теперь вопрос: как из js заставить карту обновиться, перечитав все тайлы? map.update(); не работает (map - объект карты, естественно). Сейчас приходится делать так:

 

z=map.getZoom();

map.setZoom(z-1);

map.setZoom(z);

11 комментариев
map.redraw()
Константин
28 января 2016, 08:11
map.redraw() почему-то не делает ничего.
Sergey Konstantinov
28 января 2016, 08:11
Попробуйте удалить слой тайлов и добавить его снова. Это должно быть эквивалентно перезапросу всех картинок.
Если не помогает, то можно в методе getTileUrl объекта YMaps.TileDataSource приписывать GET-параметр к URL, т.е. было:
http://your.domain/x-y-z.png?v=1
Хотите обновить, меняете шаблон на
http://your.domain/x-y-z.png?v=2
И вызываете redraw либо удаляете/добавляете слой.
redrow тут не причем

но вот шаблон урла в tileDataSource все таки нужно будет изменить,
а потом вызвать map.update(), вы сразу выбрали правильный метод, но дело в том, что сейчас тайлы реализованы так, что когда им повторно говорят показать один и тот же адрес, они этот вызов игнорируют.
redrAw конечно
Константин
28 января 2016, 08:11
еще вопрос: для пересчета из широты-долготы в коорданаты на тайле и обратно использовал известные формулы для пересчета меркатор-проекции, но то ли формулы не те, то ли еще что, но по координате y (по широте) получается небольшая погрешность. Сейчас я просто ввел поправочные коэффициенты, но хотелось бы узнать "правильную" формулу.
Для получения тайловых координат воспользуйтесь классом YMaps.TileCoordinates.
Константин
28 января 2016, 08:11
Это замечательно, но мне эти манипуляции нужно проводить во время формирования тайла, т.е. на сервере.
Sergey Konstantinov
28 января 2016, 08:11
Привожу код на JavaScript.

1. Географические координаты в меркаторовы:
   var Rn = 6378137, // Экваториальный радиус
        e = 0.0818191908426, // Эксцентриситет
        esinLat = e * Math.sin(latitude);
function geoToMercator (longitude, latitude) {
    var tan_temp = Math.tan(Math.PI / 4.0 + latitude / 2.0),
         pow_temp = Math.pow(Math.tan(Math.PI / 4.0 + Math.asin(esinLat) / 2), e),
        U = tan_temp / pow_temp;

    return new Point(Rn * longitude, Rn * Math.log(U));
}
Широта и долгота задаются В РАДИАНАХ.

2. Преобразование меркаторовых координат в тайловые (пиксели на поседнем масштабе):
    var equatorLength = 40075016.685578488, //Длина экватора
         worldSize = Math.pow(2, 31), // Размер мира в пикселах
         a = worldSize / equatorLength,
         b = equatorLength /2;

function mercatorToPixels (p) {
    return new Point(
        Math.round((this._b + p.x) * this._a),
        Math.round((this._b - p.y) * this._a)
    );
}
Константин
28 января 2016, 08:11
Спасибо! Работает! А обратное преобразование?
Sergey Konstantinov
28 января 2016, 08:11
Обратное преобразование выводится из прямого.

Пиксели -> меркаторовы координаты:

function pixelsToMercator (p) {
    return new Point(
        p.x / a - b,
        b - p.y / a
    );
}
Меркаторовы координаты -> географические:

function mercatorToGeo (p) {
    // Предвычисленные коэффициенты согласно WGS84
   var ab = 0.00335655146887969400,
        bb = 0.00000657187271079536,
        cb = 0.00000001764564338702,
        db = 0.00000000005328478445;

    var xphi = Math.PI/2 - 2 * Math.atan(1 / Math.exp(p.y/Rn));

    var latitude = xphi + ab * Math.sin(2 * xphi) + bb * Math.sin(4 * xphi) + cb * Math.sin(6 * xphi) + db * Math.sin(8 * xphi);
    var longitude = p.x/Rn;

    return new YMaps.GeoPoint(longitude * 180 / Math.PI, latitude * 180 / Math.PI, unbounded);
}