Балун, выходящий за пределы карты
Балун можно отображать в пейне, границы которого выходят за пределы карты. Это удобно, когда карта маленького размера, но в балуне нужно отобразить большое количество информации.
В этом примере дополнительно к использованию опции отображения балуна во внешнем пейне установлено слежение за текущим положением точки привязки, в момент перемещения которой за пределы видимой области карты, балун снова помещается во внутренний пейн.
index.html
balloon_out_of_map.js
<!DOCTYPE html>
<html>
<head>
<title>Балун, выходящий за пределы карты</title>
<meta
http-equiv="Content-Type"
content="text/html; charset=utf-8"
/>
<!--
Укажите свой API-ключ. Тестовый ключ НЕ БУДЕТ работать на других сайтах.
Получить ключ можно в Кабинете разработчика: https://developer.tech.yandex.ru/keys/
-->
<script
src="https://api-maps.yandex.ru/2.1/?lang=ru_RU&apikey=<ваш API-ключ>"
type="text/javascript"
></script>
<script src="balloon_out_of_map.js" type="text/javascript"></script>
<style>
#map {
width: 350px;
height: 250px;
margin: 60px;
}
</style>
</head>
<body>
<div id="map"></div>
</body>
</html>
var myMap;
ymaps.ready(function () {
myMap = new ymaps.Map(
"map",
{
zoom: 4,
center: [54.78, 30.08],
controls: [],
},
{
searchControlProvider: "yandex#search",
}
);
var myPlacemark = new ymaps.Placemark(
[55.76, 37.64],
{
balloonContent: "Я вышел за границы карты",
},
{
balloonPanelMaxMapArea: 0,
}
);
myMap.geoObjects.add(myPlacemark);
observeEvents(myMap);
myPlacemark.balloon.open();
});
function observeEvents(map) {
var mapEventsGroup;
map.geoObjects.each(function (geoObject) {
geoObject.balloon.events
// При открытии балуна начинаем слушать изменение центра карты.
.add("open", function (e1) {
var placemark = e1.get("target");
// Вызываем функцию в двух случаях:
mapEventsGroup = map.events
.group()
// 1) в начале движения (если балун во внешнем контейнере);
.add("actiontick", function (e2) {
if (
placemark.options.get("balloonPane") ==
"outerBalloon"
) {
setBalloonPane(map, placemark, e2.get("tick"));
}
})
// 2) в конце движения (если балун во внутреннем контейнере).
.add("actiontickcomplete", function (e2) {
if (
placemark.options.get("balloonPane") !=
"outerBalloon"
) {
setBalloonPane(map, placemark, e2.get("tick"));
}
});
// Вызываем функцию сразу после открытия.
setBalloonPane(map, placemark);
})
// При закрытии балуна удаляем слушатели.
.add("close", function () {
mapEventsGroup.removeAll();
});
});
}
function setBalloonPane(map, placemark, mapData) {
mapData = mapData || {
globalPixelCenter: map.getGlobalPixelCenter(),
zoom: map.getZoom(),
};
var mapSize = map.container.getSize(),
mapBounds = [
[
mapData.globalPixelCenter[0] - mapSize[0] / 2,
mapData.globalPixelCenter[1] - mapSize[1] / 2,
],
[
mapData.globalPixelCenter[0] + mapSize[0] / 2,
mapData.globalPixelCenter[1] + mapSize[1] / 2,
],
],
balloonPosition = placemark.balloon.getPosition(),
// Используется при изменении зума.
zoomFactor = Math.pow(2, mapData.zoom - map.getZoom()),
// Определяем, попадает ли точка привязки балуна в видимую область карты.
pointInBounds = ymaps.util.pixelBounds.containsPoint(mapBounds, [
balloonPosition[0] * zoomFactor,
balloonPosition[1] * zoomFactor,
]),
isInOutersPane =
placemark.options.get("balloonPane") == "outerBalloon";
// Если точка привязки не попадает в видимую область карты, переносим балун во внутренний контейнер
if (!pointInBounds && isInOutersPane) {
placemark.options.set({
balloonPane: "balloon",
balloonShadowPane: "shadows",
});
// и наоборот.
} else if (pointInBounds && !isInOutersPane) {
placemark.options.set({
balloonPane: "outerBalloon",
balloonShadowPane: "outerBalloon",
});
}
}