Настройка размера метки на разных зумах

Open in CodeSandbox

В данном примере показано, как управлять размером метки в зависимости от уровня зума на карте. Размер первой метки будет линейно зависеть от текущего уровня зума, а размер второй метки - квадратично.

Создание своего макета метки происходит при помощи фабрики макетов.

Для того чтобы узнать, в какой момент нам необходимо изменять размер метки, мы подписываемся на событие boundschange.

<!DOCTYPE html>
<html>
    <head>
        <meta
            http-equiv="Content-Type"
            content="text/html; charset=utf-8"
        />
        <title>Настройка размера метки на разных зумах</title>
        <!--
            Укажите свой API-ключ. Тестовый ключ НЕ БУДЕТ работать на других сайтах.
            Получить ключ можно в Кабинете разработчика: https://developer.tech.yandex.ru/keys/
        -->
        <script
            src="https://api-maps.yandex.ru/2.1/?lang=ru_RU&amp;apikey=<ваш API-ключ>"
            type="text/javascript"
        ></script>
        <script
            src="scalable_placemarks.js"
            type="text/javascript"
        ></script>
        <style type="text/css">
            html,
            body,
            #map,
            .placemark {
                width: 100%;
                height: 100%;
                padding: 0;
                margin: 0;
            }
            .placemark {
                background-image: url("img/pin_circle.svg");
                background-size: 100%;
            }
        </style>
    </head>
    <body>
        <div id="map"></div>
    </body>
</html>
var createChipsLayout = function (calculateSize) {
    // Создадим макет метки.
    var Chips = ymaps.templateLayoutFactory.createClass(
        '<div class="placemark"></div>',
        {
            build: function () {
                Chips.superclass.build.call(this);
                var map = this.getData().geoObject.getMap();
                if (!this.inited) {
                    this.inited = true;
                    // Получим текущий уровень зума.
                    var zoom = map.getZoom();
                    // Подпишемся на событие изменения области просмотра карты.
                    map.events.add(
                        "boundschange",
                        function () {
                            // Запустим перестраивание макета при изменении уровня зума.
                            var currentZoom = map.getZoom();
                            if (currentZoom != zoom) {
                                zoom = currentZoom;
                                this.rebuild();
                            }
                        },
                        this
                    );
                }
                var options = this.getData().options,
                    // Получим размер метки в зависимости от уровня зума.
                    size = calculateSize(map.getZoom()),
                    element =
                        this.getParentElement().getElementsByClassName(
                            "placemark"
                        )[0],
                    // По умолчанию при задании своего HTML макета фигура активной области не задается,
                    // и её нужно задать самостоятельно.
                    // Создадим фигуру активной области "Круг".
                    circleShape = {
                        type: "Circle",
                        coordinates: [0, 0],
                        radius: size / 2,
                    };
                // Зададим высоту и ширину метки.
                element.style.width = element.style.height = size + "px";
                // Зададим смещение.
                element.style.marginLeft = element.style.marginTop =
                    -size / 2 + "px";
                // Зададим фигуру активной области.
                options.set("shape", circleShape);
            },
        }
    );

    return Chips;
};

ymaps.ready(function () {
    var map = new ymaps.Map("map", {
        center: [55.755249, 37.617437],
        zoom: 4,
    });

    map.geoObjects.add(
        new ymaps.Placemark(
            [55.755249, 36.317437],
            {
                balloonContent:
                    "Линейная зависимость размера метки от уровня зума",
                hintContent: "Линейная зависимость",
            },
            {
                iconLayout: createChipsLayout(function (zoom) {
                    // Минимальный размер метки будет 8px, а максимальный мы ограничивать не будем.
                    // Размер метки будет расти с линейной зависимостью от уровня зума.
                    return 4 * zoom + 8;
                }),
            }
        )
    );

    map.geoObjects.add(
        new ymaps.Placemark(
            [55.755249, 37.617437],
            {
                balloonContent:
                    "Квадратичная зависимость размера метки от уровня зума",
                hintContent: "Квадратичная зависимость",
            },
            {
                iconLayout: createChipsLayout(function (zoom) {
                    // Минимальный размер метки будет 8px, а максимальный 200px.
                    // Размер метки будет расти с квадратичной зависимостью от уровня зума.
                    return Math.min(Math.pow(zoom, 2) + 8, 200);
                }),
            }
        )
    );
});