Yandex Map v3 setPosition относительно попапа
Всем привет. У меня есть кастомный попап при клике на точку карты. Как можно сделать подскролл при клике на точку, что бы по центру был попап?
/** Yandex Map type - Feature to clusterize on a map */
type Feature = GenericPointFeature<LngLat>;
const openPopup = (feature: Feature, e: MouseEvent) => {
mapMarkerActive.htmlElement = e.target as HTMLImageElement
mapMarkerActive.htmlElement.src = '/images/map/marker_active.svg'
map.setLocation({
center: [
Number(feature.properties?.longitude),
Number(feature.properties?.latitude),
] as LngLat,
duration: 500,
})
popup = new YMapMarker(
{
coordinates: feature.geometry.coordinates,
},
popupTemplate(feature)
)
map.addChild(popup)
}
Я вижу это так, что вот тут для latitude нужно вычесть высоту попапа, но как правильно вычесть из координат пиксели, да еще и в зависимости от зума на карте?
map.setLocation({
center: [
Number(feature.properties?.longitude),
Number(feature.properties?.latitude),
] as LngLat,
duration: 500,
})
Нашел в документации вот такие методы https://yandex.com/dev/jsapi-v2-1/doc/en/v2-1/ref/reference/map.Converter Но как будто это немножно не то. Да и для 3.0 версии не нашел эти методы в документации.
Ответы (1 шт):
В общем отчасти спас ChatGPT, но немного было немного нето по координатам. Методом подбора и тестов вывел вот такую функцию
/** Yandex Map type - Feature to clusterize on a map */
type Feature = GenericPointFeature<LngLat>;
const openPopup = (feature: Feature, e: MouseEvent) => {
mapMarkerActive.htmlElement = e.target as HTMLImageElement
mapMarkerActive.htmlElement.src = '/images/map/marker_active.svg'
map.setLocation({
center: [
Number(feature.properties?.longitude),
// 70 это как раз на сколько нужно сместить карту в пикселях относительно маркера/точки
Number(feature.properties?.latitude) + yandexPixelsToLatitude(70, map.zoom),
] as LngLat,
duration: 500,
})
popup = new YMapMarker(
{
coordinates: feature.geometry.coordinates,
},
popupTemplate(feature)
)
map.addChild(popup)
}
function yandexPixelsToLatitude(pixels, zoom) {
// Размер тайла карты, обычно равен 256 пикселей.
const tile_size = 256;
// Масштаб, который изменяется в зависимости от уровня зума.
const scale = 256 * Math.pow(2, zoom);
// Радиус Земли в метрах.
const earth_radius = 6378137;
// Смещение начала координат для преобразования пикселей.
const origin_shift = tile_size / 2.0;
// Количество метров на пиксель, зависящее от масштаба.
// earth_radius * Math.PI * 2 — это длина экватора Земли в метрах.
// tile_size * scale — это количество пикселей на карте при данном масштабе.
const metersPerPixel = (earth_radius * Math.PI * 2) / scale;
// Вычисление координаты 'y' в метрах на основе пиксельного смещения от начала координат.
// (origin_shift - pixels) — это смещение от начала координат в пикселях.
const y = ((origin_shift - pixels) * metersPerPixel) / earth_radius;
// Преобразование 'y' в радианы и вычисление широты.
// Math.exp(y) — это экспоненциальная функция, которая нужна для обратного преобразования из метров в координаты.
// Math.atan() — это арктангенс, который преобразует значение обратно в радианы.
// Умножение на 360 / Math.PI - 90 преобразует радианы в градусы и сдвигает значение, чтобы получить широту.
return ((Math.atan(Math.exp(y)) * 360) / Math.PI - 90)*500;
}
500 это уже мой коэффициент, которые мне дал верный результат.