Приветствую!
Вопрос знатокам.
Документация на api карт говорит, что максимально доступный зум = 23, но при этом тайлы имеются только для масштаба 19 и увеличить далее не имеется возможности.
Проблема заключается в том, что на карту добавляется дополнительный слой wms, у которого детальное отображение информации начиается на 20-21 зуме, но сама карта блокирует увеличение дальше.
Каким образом можно сделать так, чтобы основная подложка Яндекса карты, в случае отсутствия тайлов нужного масшатаба делала искусственное увеличение тайлов и не ограничивала максимально достуспный зум.
Решено.
Пример увеличенного масштабирования карты
ymaps.ready(function () {
/* получаем из хранилища встроенный тип слоя */
let YandexMapLayer = ymaps.layer.storage.get('yandex#map');
/* Дочерний класс слоя с перекрытием метода getZoomRange */
let CustomMapLayer = function () {
/* Calling the parent's constructor */
CustomMapLayer.superclass.constructor.call(this);
/* в служебных полях объявляем максимально доступный зум и интересующую нас степерь масштабирования слоя*/
this._maxAvaliableZoom = 19;
this._zoomRange = [0, 23];
}
/* выполняем наследование */
ymaps.util.augment(CustomMapLayer, YandexMapLayer, {
/* Переопределяем в наследнике метод getZoomRange */
getZoomRange: function (point) {
let _this = this;
/* Вызываем асинхронный метод родительского класса. */
CustomMapLayer.superclass.getZoomRange.call(this, point).then(function(zoomRange) {
/*
* на случай, если в какой-то местности доступный уровень зума отличается от значения 19
* - делаем обновление локального поля (для дайльнейшего расчета степени искусственного увеличения тайлов)
* но на практике - тайлы с уровнем зума 19 есть везде (Москва и любая степь...), более 19 - тайлов нет
*/
if (zoomRange[1] != _this._maxAvaliableZoom) {
_this._maxAvaliableZoom = zoomRange[1];
}
});
return ymaps.vow.resolve(_this._zoomRange);
}
});
let YCustomMapLayer = function () {
let layer = new CustomMapLayer();
let defaultTileUrlTemplate = layer.getTileUrlTemplate();
/* перекрытие размера тайла */
layer.getTileSize = function(zoom) {
let pixelRatio = ymaps.util.hd.getPixelRatio();
if(zoom > layer._maxAvaliableZoom) {
/* считаем требуемую степень масштабирования тайла */
let scale = 2**(zoom - layer._maxAvaliableZoom);
let tailImageScale = scale * pixelRatio;
/* подменяем урл получения тайла - при запросе тайла требуемого масштаба - сохраняем качество отобржения карты */
/* фиксируем зум на уровне максимально доступного */
/* дополнительно делаем проверку на запрашиваемый масштаб тайла, т.к. максимально доступный масштаб изображения - 16 */
let zoomOverTileUrlTemplate = defaultTileUrlTemplate
.replace("%c", "x=%x&y=%y&z="+layer._maxAvaliableZoom)
.replace("{{ scale }}", tailImageScale > 16 ? 16: tailImageScale);
console.log("zoomOverTileUrlTemplate", zoomOverTileUrlTemplate);
layer.setTileUrlTemplate(zoomOverTileUrlTemplate);
return [256 * scale, 256 * scale];
}
/* установка дефотного шаблона url */
layer.setTileUrlTemplate(defaultTileUrlTemplate);
/* возвращем дефолтный размер тайла */
return [256, 256];
};
return layer;
};
/* регистрируем новый тип слоя */
ymaps.layer.storage.add('custom#map', YCustomMapLayer);
/* создаем новый тип карты с кастомным слоем */
let customMapType = new ymaps.MapType('Схема +', ['custom#map']);
/* регистрируем новый тип карты */
ymaps.mapType.storage.add('custom_map#map', customMapType);
/* выполняем инициализацию карты, с указанием вновь созданного типа */
myMap = new ymaps.Map(
// ID DOM-элемента, в который будет добавлена карта.
'map',
// Параметры карты.
{
// Географические координаты центра отображаемой карты.
center: [55.76, 37.64], // Москва
// Масштаб.
zoom: 19,
controls: ["zoomControl"],
type: 'custom_map#map'
}
);
/* добавляем на карту контрол выбора типа с указанием стандартных карт и вновь созданной */
myMap.controls.add(new ymaps.control.TypeSelector({
mapTypes: ['custom_map#map','yandex#map', 'yandex#hybrid', 'yandex#satellite'],
}));
});ссылки на документацию:
1. Создание собственного типа карты
2. Наследование [ util.augment ]
3. Определение плотности пикселей клиента [ util.hd ]
Дополнительно:
1. При реализации увеличенного зума для 'yandex#satellite' - в запросе тайла от сервера Яндекса параметр scale не фигурирует и не несет смысла. Качество спутникового снимка не увеличится =)
2. Карта 'yandex#hybrid' состоит из двух слоев - подложка спутниковых снимков и наложение поверх нее векторного слоя с улицами и надписями (с прозрачным фоном). Векторый слой надписей успешно поддается масштабированию с сохранением качества изображения, как и с простым типом карты, рассмотренном выше