Created
March 2, 2018 11:09
-
-
Save AnatoliyKhaulin/bc88c77c082ef764340a22b584fa0ed3 to your computer and use it in GitHub Desktop.
Yandex Map geoObjects custom balloon and pin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "type": "FeatureCollection", | |
| "features": [{ | |
| "type": "Feature", | |
| "id": 0, | |
| "geometry": { | |
| "type": "Point", | |
| "coordinates": [56.839526, 35.915296] | |
| }, | |
| "properties": { | |
| "balloonHeader": "Заголовок", | |
| "balloonCell1Title": "Заголовок ячейки", | |
| "balloonCell1Val": "Значение", | |
| "balloonCell2Title": "Заголовок ячейки", | |
| "balloonCell2Val": "Значение", | |
| "balloonCell3Title": "Заголовок ячейки", | |
| "balloonCell3Val": "Значение", | |
| "balloonFooter": "Футер", | |
| "hintContent": "" | |
| } | |
| }, | |
| ] | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Создание макета балуна | |
| MyBalloonLayout = ymaps.templateLayoutFactory.createClass( | |
| '<div id="balloonPopover" class="popover top">' + | |
| '<a class="close" href="#">×</a>' + | |
| '<div class="arrow"></div>' + | |
| '<div class="popover-inner">' + | |
| '$[[options.contentLayout observeSize minWidth=320 maxWidth=320 maxHeight=165]]' + | |
| '</div>' + | |
| '</div>', { | |
| /** | |
| * Строит экземпляр макета на основе шаблона и добавляет его в родительский HTML-элемент. | |
| * @see https://api.yandex.ru/maps/doc/jsapi/2.1/ref/reference/layout.templateBased.Base.xml#build | |
| * @function | |
| * @name build | |
| */ | |
| build: function () { | |
| this.constructor.superclass.build.call(this); | |
| this._$element = $('.popover', this.getParentElement()); | |
| this.applyElementOffset(); | |
| this._$element.find('.close') | |
| .on('click', $.proxy(this.onCloseClick, this)); | |
| }, | |
| /** | |
| * Удаляет содержимое макета из DOM. | |
| * @see https://api.yandex.ru/maps/doc/jsapi/2.1/ref/reference/layout.templateBased.Base.xml#clear | |
| * @function | |
| * @name clear | |
| */ | |
| clear: function () { | |
| this._$element.find('.close') | |
| .off('click'); | |
| this.constructor.superclass.clear.call(this); | |
| }, | |
| /** | |
| * Метод будет вызван системой шаблонов АПИ при изменении размеров вложенного макета. | |
| * @see https://api.yandex.ru/maps/doc/jsapi/2.1/ref/reference/IBalloonLayout.xml#event-userclose | |
| * @function | |
| * @name onSublayoutSizeChange | |
| */ | |
| onSublayoutSizeChange: function () { | |
| MyBalloonLayout.superclass.onSublayoutSizeChange.apply(this, arguments); | |
| if(!this._isElement(this._$element)) { | |
| return; | |
| } | |
| this.applyElementOffset(); | |
| this.events.fire('shapechange'); | |
| }, | |
| /** | |
| * Сдвигаем балун, чтобы "хвостик" указывал на точку привязки. | |
| * @see https://api.yandex.ru/maps/doc/jsapi/2.1/ref/reference/IBalloonLayout.xml#event-userclose | |
| * @function | |
| * @name applyElementOffset | |
| */ | |
| applyElementOffset: function () { | |
| this._$element.css({ | |
| left: -(this._$element[0].offsetWidth / 2), | |
| top: -(this._$element[0].offsetHeight + this._$element.find('.arrow')[0].offsetHeight + 20) | |
| }); | |
| }, | |
| /** | |
| * Закрывает балун при клике на крестик, кидая событие "userclose" на макете. | |
| * @see https://api.yandex.ru/maps/doc/jsapi/2.1/ref/reference/IBalloonLayout.xml#event-userclose | |
| * @function | |
| * @name onCloseClick | |
| */ | |
| onCloseClick: function (e) { | |
| e.preventDefault(); | |
| this.events.fire('userclose'); | |
| }, | |
| /** | |
| * Используется для автопозиционирования (balloonAutoPan). | |
| * @see https://api.yandex.ru/maps/doc/jsapi/2.1/ref/reference/ILayout.xml#getClientBounds | |
| * @function | |
| * @name getClientBounds | |
| * @returns {Number[][]} Координаты левого верхнего и правого нижнего углов шаблона относительно точки привязки. | |
| */ | |
| getShape: function () { | |
| if(!this._isElement(this._$element)) { | |
| return MyBalloonLayout.superclass.getShape.call(this); | |
| } | |
| var position = this._$element.position(); | |
| return new ymaps.shape.Rectangle(new ymaps.geometry.pixel.Rectangle([ | |
| [position.left, position.top], [ | |
| position.left + this._$element[0].offsetWidth, | |
| position.top + this._$element[0].offsetHeight + this._$element.find('.arrow')[0].offsetHeight | |
| ] | |
| ])); | |
| }, | |
| /** | |
| * Проверяем наличие элемента (в ИЕ и Опере его еще может не быть). | |
| * @function | |
| * @private | |
| * @name _isElement | |
| * @param {jQuery} [element] Элемент. | |
| * @returns {Boolean} Флаг наличия. | |
| */ | |
| _isElement: function (element) { | |
| return element && element[0] && element.find('.arrow')[0]; | |
| } | |
| }), | |
| // Создание вложенного макета содержимого балуна. | |
| MyBalloonContentLayout = ymaps.templateLayoutFactory.createClass( | |
| '<h5 class="popover-title">$[properties.balloonHeader]</h5>' + | |
| '<div class="row">' + | |
| '<div class="cell">' + | |
| '<span>$[properties.balloonCell1Title]</span>' + | |
| '<span class="strong">$[properties.balloonCell1Val]</span>' + | |
| '</div>' + | |
| '<div class="cell">' + | |
| '<span>$[properties.balloonCell2Title]</span>' + | |
| '<span class="strong">$[properties.balloonCell2Val]</span>' + | |
| '</div>' + | |
| '<div class="cell">' + | |
| '<span>$[properties.balloonCell3Title]</span>' + | |
| '<span class="strong">$[properties.balloonCell3Val]</span>' + | |
| '</div>' + | |
| '</div>' + | |
| '<div class="popover-footer">$[properties.balloonFooter]</div>' | |
| ), | |
| objectManager = new ymaps.ObjectManager({ | |
| // Чтобы метки начали кластеризоваться, выставляем опцию. | |
| clusterize: false, | |
| // ObjectManager принимает те же опции, что и кластеризатор. | |
| gridSize: 32, | |
| clusterDisableClickZoom: false, | |
| }); | |
| objectManager.objects.options.set({ | |
| balloonLayout: MyBalloonLayout, | |
| balloonContentLayout: MyBalloonContentLayout, | |
| balloonPanelMaxMapArea: 0, | |
| iconLayout: 'default#image', | |
| iconImageHref: './images/contacts/map_marker.svg', | |
| iconImageSize: [30, 37], | |
| iconImageOffset: [-20, -33], | |
| }); | |
| myMap.geoObjects.add(objectManager); | |
| $.ajax({ | |
| url: "./geo.json" | |
| }).done(function(data) { | |
| objectManager.add(data); | |
| }); | |
| // show balloon hover | |
| objectManager.objects.events.add('mouseenter', function (e) { | |
| var objectId = e.get('objectId'); | |
| objectManager.objects.balloon.open(objectId); | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment