Демо:

https://codepen.io/ildar-meyker/pen/wvYZQmB

Плагины:

https://jquery.com/

https://yandex.com/dev/maps/

Подключение:

//

<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.4/dist/jquery.min.js"></script>


<script
    src="https://api-maps.yandex.ru/2.1/?apikey=4ee83d51-9c82-4832-ae32-283ef606144b
&lang=ru_RU"
    type="text/javascript"
></script>

Разметка:

//

<div class="map">
    <div class="map__container">
        <div
            id="map"
            style="width: 100%; height: 100%"
            data-items='[{"coords":[59.779398, 30.459721],"tip":"Содержание всплывающей подсказки","title":"Альфа-Авто","description":"Россия, Адлер, ул. Авиационная, 34/3, Пн-Сб с 9:00 до 19:00. Вс: выходной, +7 (862) 291 48 48"},{"coords":[59.78467,30.445594],"tip":"Содержание всплывающей подсказки","title":"Альфа-Авто","description":"Россия, Адлер, ул. Авиационная, 34/3,   Пн-Сб с 9:00 до 19:00. Вс: выходной, +7 (862) 291 48 48"}]'
        ></div>
    </div>
</div>

Стили:

//

@mixin reset-button {
    display: inline-block;
    border: 0;
    padding: 0;
    background: none;
    font-family: inherit;
    cursor: pointer;
}

.map {
    &__container {
        height: 40.5rem;
        background: #f3f3f3;

        [class*="ymaps-2"][class*="-ground-pane"] {
            filter: #{"grayscale()"};
        }
    }
}


.card-map {
    position: absolute;
    width: 332px;
    font-size: 1.8rem;
    line-height: calc(24 / 18);
    color: #ffffff;

    &--static {
        position: relative;
    }

    &__body {
        background: #204a8f;
        border-radius: 0.5rem;
        padding: 1.6rem;
    }

    &__title {
    }

    &__desc {
        margin-top: 1rem;
    }

    &__close {
        @include reset-button;
        position: absolute;
        right: 0;
        top: 0;
        padding: 1rem;
        font-size: 3rem;
        line-height: 0.5;
        color: #fff;
    }
}

Инициализация:

//

function init() {
    let counterId = 0;
    const items = $("#map").data("items");
    const points = items.map((item) => {
        return {
            type: "Feature",
            id: ++counterId,
            geometry: {
                type: "Point",
                coordinates: item.coords,
            },
            properties: {
                hintContent: item.tip,
                balloonHeader: item.title,
                balloonContent: item.description,
            },
        };
    });
    console.log(points);

    const myMap = new ymaps.Map(
        "map",
        {
            center: [59.779398, 30.459721],
            zoom: 15,
        },
        {
            searchControlProvider: "yandex#search",
        }
    );

    const MyBalloonLayout = ymaps.templateLayoutFactory.createClass(
        '<div class="card-map">' +
            '<button class="card-map__close">&times;</button>' +
            '<div class="card-map__body">' +
            "$[[options.contentLayout observeSize minWidth=300 maxWidth=300 maxHeight=350]]" +
            "</div>" +
            "</div>",
        {
            build: function () {
                this.constructor.superclass.build.call(this);

                this._$element = $(".card-map", this.getParentElement());

                this.applyElementOffset();

                this._$element
                    .find(".card-map__close")
                    .on("click", $.proxy(this.onCloseClick, this));
            },

            clear: function () {
                this._$element.find(".card-map__close").off("click");

                this.constructor.superclass.clear.call(this);
            },

            applyElementOffset: function () {
                this._$element.css({
                    left: -(this._$element[0].offsetWidth / 2),
                    top: -this._$element[0].offsetHeight - 40,
                });
            },

            onCloseClick: function (e) {
                e.preventDefault();

                this.events.fire("userclose");
            },
        }
    );

    // Создание вложенного макета содержимого балуна.
    const MyBalloonContentLayout = ymaps.templateLayoutFactory.createClass(
        '<div class="card-map__title">$[properties.balloonHeader]</div>' +
            '<div class="card-map__desc">$[properties.balloonContent]</div>'
    );

    const defaultOptions = {
        balloonShadow: false,
        balloonLayout: MyBalloonLayout,
        balloonContentLayout: MyBalloonContentLayout,
        balloonPanelMaxMapArea: 0,
        hideIconOnBalloonOpen: false,
        iconLayout: "default#image",
        iconImageHref: "img/markers/location-white.svg",
        iconImageSize: [28, 28],
        iconImageOffset: [-14, -28],
    };

    const activeOptions = {
        ...defaultOptions,
        iconImageHref: "img/markers/location-blue.svg",
    };

    var objectManager = new ymaps.ObjectManager({
        // Включаем кластеризацию.
        clusterize: true,
        // Опции кластеров задаются с префиксом 'cluster'.
        clusterHasBalloon: false,
    });

    objectManager.clusters.options.set({
        preset: "islands#blueClusterIcons",
        clusterIconColor: "#204A8F",
    });

    objectManager.objects.options.set(defaultOptions);

    objectManager.objects.events.add("balloonopen", (e) => {
        objectManager.objects.setObjectOptions(
            e.get("objectId"),
            activeOptions
        );
    });

    objectManager.objects.events.add("balloonclose", (e) => {
        objectManager.objects.setObjectOptions(
            e.get("objectId"),
            defaultOptions
        );
    });

    objectManager.add(points);

    myMap.geoObjects.add(objectManager);
    myMap.behaviors.disable("scrollZoom");
}

if (typeof ymaps !== "undefined" && $("#map").length !== 0) {
    ymaps.ready(init);
}
Рубрики: модуль

0 комментариев

Добавить комментарий

Avatar placeholder

Ваш адрес email не будет опубликован. Обязательные поля помечены *