Custom Yandex Maps

ver.2.0.1
от 13.01.2026 16:01

Описание

Руководство по API

В head страницы подключить api <script src="https://api-maps.yandex.ru/2.1/?&lang=ru_RU" type="text/javascript"></script>

Основные возможности

  1. Возможность использования одной или нескольких меток
    Позволяет пользователю добавлять на карту одну или несколько меток. Это удобно для обозначения различных точек интереса, таких как достопримечательности, магазины, офисы и т.д.
  2. Подстройка масштаба карты под одну или все метки
    Автоматически настраивает масштаб карты так, чтобы все добавленные метки были видны на экране. Это помогает пользователю сразу увидеть все важные точки без необходимости ручной настройки масштаба.
  3. Выбор, какие элементы на карте отображать
    Позволяет пользователю выбирать, какие элементы карты будут отображаться. Например, можно включить или выключить отображение дорог, зданий, рек, границ и других объектов.
  4. Можно задавать координаты для одной или нескольких меток, а также их подсказки
    Дает возможность пользователю задавать точные координаты для меток и добавлять всплывающие подсказки с дополнительной информацией, которая будет отображаться при наведении или клике на метку.
  5. Содержимое всплывающей подсказки
    Определяет, какая информация будет отображаться во всплывающей подсказке при взаимодействии с меткой. Это может быть текст, изображения, ссылки и другая полезная информация.
  6. Путь до иконки маркера
    Позволяет задавать пользовательские иконки для меток, указывая путь к изображению. Это позволяет использовать уникальные иконки, которые лучше соответствуют тематике метки.
  7. Размер маркера
    Позволяет настраивать размер меток на карте. Это полезно для выделения более важных меток или для улучшения визуального восприятия карты.
  8. Смещение маркера
    Дает возможность задавать смещение метки относительно её координат. Это может быть полезно для точного позиционирования метки на карте, особенно если стандартное положение перекрывает важные детали.
JS
от 13.01.2026 16:01
Параметры
multi
Одна точка на карте или их несколько.
Тип:
boolean
Значение по умолчанию:
false
selector
ID элемента куда будет вставляться карта.
Тип:
string
Значение по умолчанию:
"map"
zoom
Масштаб карты.
Тип:
sting|number
Значение по умолчанию:
16
Если ввести all, то на карте должны уместиться все точки.
controls
Какие элементы будут видны на карте.
Тип:
array
Значение по умолчанию:
"zoomControl"

Доступные параметры:

[]       	        Запретить все
default 	        Все элементы
geolocationControl 	Геолокации
searchControl 	   	Поисковая строка
routeEditor 	    	Редактора маршрута
zoomControl 	    	Ползунок масштаба
fullscreenControl 	Полноэкранный режима
trafficControl 	    	Пробки
typeSelector 	    	Тип карты
rulerControl 	    	Измерение расстояний
coords
Коррдинаты точки.
Тип:
array
Значение по умолчанию:
[55.050432, 60.109599]

Если включен параметр multi: true, то массив координат будет:

{
    name: "Миасс",
    title: "miass",
    coords: [55.050432, 60.109599],
    balloonContent: "Cодержимое всплывающей подсказки",
}
balloonContent
Содержимое всплывающей подсказки.
Тип:
string
iconImageHref
Путь до иконки маркера.
Тип:
string
iconImageSize
Размер маркера.
Тип:
array
Значение по умолчанию:
[24, 24]
iconImageOffset
Смещение маркера.
Тип:
array
Значение по умолчанию:
[0, 0]
Как юзать
Карта с одним маркером
      new CustomMaps({
    selector: 'map1',
    coords: [55.050432, 60.109599],
});
    
Карта с несколькими маркерами
      new CustomMaps({
    multi: true,
    selector: 'map2',
    zoom: 'all',
    coords: [
        {
            name: 'Миасс',
            title: 'miass',
            coords: [55.050432, 60.109599],
            balloonContent: 'Cодержимое всплывающей подсказки "Миасс"',
        },
        {
            name: 'Челябинск',
            title: 'chelyabinsk',
            coords: [55.159902, 61.402554],
            balloonContent: 'Cодержимое всплывающей подсказки "Челябинск"',
        },
        {
            name: 'Озерск',
            title: 'ozersk',
            coords: [55.763189, 60.707608],
            balloonContent: 'Cодержимое всплывающей подсказки "Озерск"',
        },
        {
            name: 'Кыштым',
            title: 'kyshtym',
            coords: [55.707882, 60.538958],
            balloonContent: 'Cодержимое всплывающей подсказки "Кыштым"',
        },
        {
            name: 'Карабаш',
            title: 'karabash',
            coords: [55.488371, 60.203087],
            balloonContent: 'Cодержимое всплывающей подсказки "Карабаш"',
        },
        {
            name: 'Златоуст',
            title: 'zlatoust',
            coords: [55.173113, 59.672425],
            balloonContent: 'Cодержимое всплывающей подсказки "Златоуст"',
        },
    ],
});
    
Код
      /**
 *
 * Custom Map
 * Открытие модальных окон
 *
 * @author      Mihail Pridannikov
 * @copyright   2025-2026, Mihail Pridannikov
 * @license MIT
 * @version     2.0.1
 * @release     January 13, 2026
 * @link        https://github.com/mihail-174/custom_popup
 *
 */

window.CustomMaps = function(settingsCustom) {
    this.deepMergeObjects = function (obj1, obj2) {
        const result = {};
        for (const key in obj2) {
            if (obj2.hasOwnProperty(key)) {
                if (typeof obj2[key] === "object" && obj1.hasOwnProperty(key) && typeof obj1[key] === "object") {
                    result[key] = this.deepMergeObjects(obj1[key], obj2[key]);
                } else {
                    result[key] = obj2[key];
                }
            }
        }
        for (const key in obj1) {
            if (obj1.hasOwnProperty(key) && !result.hasOwnProperty(key)) {
                if (typeof obj1[key] === "object") {
                    result[key] = this.deepMergeObjects(obj1[key], {});
                } else {
                    result[key] = obj1[key];
                }
            }
        }
        return result;
    }

    const DEFAULT_SETTINGS = {
        multi: false,
        selector: 'map',
        zoom: 16,
        coords: [55.050432, 60.109599],
        // coords: [
        //     {
        //         name: 'Миасс',
        //         title: 'miass',
        //         coords: [55.050432, 60.109599],
        //         balloonContent: '',
        //     }
        // ],
        // controls: ["zoomControl", "fullscreenControl"],
        balloonContent: '',
        iconImageHref: 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPScxLjEnIGlkPSdMYXllcl8xJyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHhtbG5zOnhsaW5rPSdodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rJyB4PScwcHgnIHk9JzBweCcgdmlld0JveD0nMCAwIDUxMS45OTkgNTExLjk5OScgc3R5bGU9J2VuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNTExLjk5OSA1MTEuOTk5OycgeG1sOnNwYWNlPSdwcmVzZXJ2ZSc+PHBhdGggc3R5bGU9J2ZpbGw6I0VFMzg0MDsnIGQ9J000NTQuODQ4LDE5OC44NDhjMCwxNTkuMjI1LTE3OS43NTEsMzA2LjY4OS0xNzkuNzUxLDMwNi42ODljLTEwLjUwMyw4LjYxNy0yNy42OTIsOC42MTctMzguMTk1LDAgYzAsMC0xNzkuNzUxLTE0Ny40NjQtMTc5Ljc1MS0zMDYuNjg5QzU3LjE1Myw4OS4wMjcsMTQ2LjE4LDAsMjU2LDBTNDU0Ljg0OCw4OS4wMjcsNDU0Ljg0OCwxOTguODQ4eicvPjxwYXRoIHN0eWxlPSdmaWxsOiNGRkUxRDY7JyBkPSdNMjU2LDI5OC44OWMtNTUuMTY0LDAtMTAwLjA0MS00NC44NzktMTAwLjA0MS0xMDAuMDQxUzIwMC44MzgsOTguODA2LDI1Niw5OC44MDYgczEwMC4wNDEsNDQuODc5LDEwMC4wNDEsMTAwLjA0MVMzMTEuMTY0LDI5OC44OSwyNTYsMjk4Ljg5eicvPjwvc3ZnPg==',
        iconImageSize: [24, 24],
        iconImageOffset: [0, 0],
    }

    let settings = this.deepMergeObjects(DEFAULT_SETTINGS, settingsCustom);

    this.init = function () {
        if (settings.multi) {
            if (typeof ymaps !== "undefined") {
                ymaps.ready(() => {
                    let myMap = new ymaps.Map(settings.selector, {
                            center: [],
                            zoom: settings.zoom,
                            controls: settings.controls || ["zoomControl", "fullscreenControl"]
                        }, {
                            searchControlProvider: 'yandex#search',
                            suppressMapOpenBlock: true
                        }),
                        objectManager = new ymaps.ObjectManager({
                            clusterize: true,
                            gridSize: 32,
                            clusterDisableClickZoom: false
                        });

                    Object.values(settings.coords).map((item) => {
                        myMap.geoObjects.add(
                            new ymaps.Placemark(item.coords, {
                                balloonContent: item.balloonContent,
                            }, {
                                iconLayout: 'default#image',
                                iconImageHref: settings.iconImageHref,
                                iconImageSize: settings.iconImageSize,
                                iconImageOffset: settings.iconImageOffset,
                                balloonCloseButton: true,
                                hideIconOnBalloonOpen: true,
                            })
                        );
                    });

                    if (settings.zoom === 'all') {
                        let pointsList = [];

                        Object.values(settings.coords).map((item) => {
                            pointsList.push(item.coords);
                        });
                        myMap.setBounds(ymaps.util.bounds.fromPoints(pointsList));

                        let zoomNew = myMap.getZoom();
                        myMap.setZoom(16);
                        myMap.setZoom(zoomNew);

                        window.addEventListener('resize', (e) => {
                            myMap.setBounds(ymaps.util.bounds.fromPoints(pointsList));
                            myMap.setZoom(16);
                            myMap.setZoom(zoomNew);
                        });
                    } else {
                        myMap.setBounds(myMap.geoObjects.getBounds());
                    }

                    myMap.behaviors.disable("scrollZoom");
                });
            }
        } else {
            if (typeof ymaps !== "undefined") {
                ymaps.ready(() => {
                    const myMap = new ymaps.Map(settings.selector, {
                        center: Object.values(settings.coords),
                        zoom: settings.zoom,
                        controls: settings.controls || ["zoomControl", "fullscreenControl"]
                    }, {
                        searchControlProvider: 'yandex#search',
                        suppressMapOpenBlock: true
                    });
                    const myPlacemark = new ymaps.Placemark(Object.values(settings.coords), {
                        balloonContent: settings.balloonContent,
                    }, {
                        iconLayout: 'default#image',
                        iconImageHref: settings.iconImageHref,
                        iconImageSize: settings.iconImageSize,
                        iconImageOffset: settings.iconImageOffset,
                        balloonCloseButton: true,
                        hideIconOnBalloonOpen: true,
                    });
                    myMap.geoObjects.add(myPlacemark);
                    myMap.behaviors.disable("scrollZoom");
                });
            }

        }

    }

    this.init();
}
    

Changelogs

v2.0.1
latest
от 13 января 2026
  • fix: исправление ползунка масштаба при выводе нескольких меток на карте
v2.0.0
от 29 Февраля 2025
  • Возможность использования одной или нескольких меток
  • Выбор, какие элементы на карте отображать
  • Можно задавать координаты для одной или нескольких меток, а также их подсказки
  • Содержимое всплывающей подсказки
  • Путь до иконки маркера
  • Размер маркера
  • Смещение маркера
v1.0.0
  • init