Last active
January 7, 2023 06:35
-
-
Save newbornfrontender/c58a15251f0293c490f3f5bdc0e5dc64 to your computer and use it in GitHub Desktop.
yandex map custom cluster and placemark
This file contains 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
import $ from 'jquery'; | |
// $(document).ready(() => { | |
// // Создание кластеризатора с произвольным HTML-макетом иконки кластера | |
// class CustomCluster { | |
// // Зададаем макет метки кластера | |
// createCluster() { | |
// return ymaps.templateLayoutFactory.createClass( | |
// '<div class="ymap-cluster-icon">{{ properties.geoObjects.length }}</div>', | |
// ); | |
// } | |
// // Зададаем активную область иконки кластера | |
// createIconShape() { | |
// return { | |
// type: 'Circle', | |
// coordinates: [0, 0], | |
// radius: 25, | |
// }; | |
// } | |
// } | |
// const init = () => { | |
// const clusterer = new CustomCluster; | |
// const map = new ymaps.Map( | |
// 'map', | |
// { | |
// center: [55.76, 37.64], | |
// zoom: 10, | |
// }, | |
// { | |
// searchControlProvider: 'yandex#search', | |
// }, | |
// ); | |
// const objectManager = new ymaps.ObjectManager({ | |
// // Включает кластеризацию | |
// clusterize: true, | |
// // Устанавливает размер ячейки кластеризации в пикселях | |
// gridSize: 32, | |
// }); | |
// objectManager.objects.options.set({ | |
// // Указываем тип макета | |
// iconLayout: 'default#imageWithContent', | |
// // Добавляем своё изображение иконки метки | |
// iconImageHref: 'img/marker.svg', | |
// // Указываем размеры метки | |
// iconImageSize: [50, 50], | |
// // Изменяем положение левого верхнего угла иконки относительно её точки привязки | |
// iconImageOffset: [-25, -25], | |
// // Не скрывать метку при открытии балуна | |
// hideIconOnBalloonOpen: false, | |
// }); | |
// objectManager.clusters.options.set({ | |
// clusterIconLayout: clusterer.createCluster(), | |
// clusterIconShape: clusterer.createIconShape(), | |
// }); | |
// map.geoObjects.add(objectManager); | |
// $.ajax({ | |
// url: 'data.json', | |
// }).done((data) => { | |
// objectManager.add(data); | |
// }); | |
// }; | |
// ymaps.ready(init); | |
// }); | |
// ============================================================================= | |
// ============================================================================= | |
// ============================================================================= | |
$(document).ready(() => { | |
// Создание кластеризатора с произвольным HTML-макетом иконки кластера | |
class CustomCluster { | |
// Зададаем макет метки кластера | |
createCluster() { | |
return ymaps.templateLayoutFactory.createClass( | |
'<div class="ymap-cluster-icon">{{ properties.geoObjects.length }}</div>', | |
); | |
} | |
// Зададаем активную область иконки кластера | |
createIconShape() { | |
return { | |
type: 'Circle', | |
coordinates: [0, 0], | |
radius: 25, | |
}; | |
} | |
} | |
const init = () => { | |
const coords = [ | |
[56.023, 36.988], | |
[56.025, 36.981], | |
[56.02, 36.981], | |
[56.021, 36.983], | |
[56.027, 36.987], | |
]; | |
const geoObjects = []; | |
const map = new ymaps.Map( | |
'map', | |
{ | |
center: [55.76, 37.64], | |
zoom: 10, | |
}, | |
{ | |
searchControlProvider: 'yandex#search', | |
}, | |
); | |
const cluster = new CustomCluster(); | |
const CustomBalloonLayout = ymaps.templateLayoutFactory.createClass( | |
` | |
<div class="ymap-popover"> | |
<a class="ymap-popover-close" href="/">×</a> | |
<div class="ymap-popover-arrow"></div> | |
<div class="popover-inner"> | |
$[[options.contentLayout observeSize minWidth=235 maxWidth=235 maxHeight=350]] | |
</div> | |
</div> | |
`, | |
{ | |
// Строим экземпляр макета на основе шаблона и добавляем его в родительский HTML-элемент | |
build() { | |
this.constructor.superclass.build.call(this); | |
this._$element = $('.ymap-popover', this.getParentElement()); | |
this.applyElementOffset(); | |
this._$element.find('.ymap-popover-close').on('click', $.proxy(this.onCloseClick, this)); | |
}, | |
// Удаляем содержимое макета из DOM | |
clear() { | |
this._$element.find('.ymap-popover-close').off('click'); | |
this.constructor.superclass.clear.call(this); | |
}, | |
// Метод будет вызван системой шаблонов API при изменении размеров вложенного макета | |
onSublayoutSizeChange() { | |
CustomBalloonLayout.superclass.onSublayoutSizeChange.apply(this, arguments); | |
if (!this._isElement(this._$element)) { | |
return; | |
} | |
this.applyElementOffset(); | |
this.events.fire('shapechange'); | |
}, | |
// Сдвигаем балун, чтобы "хвостик" указывал на точку привязки | |
applyElementOffset() { | |
this._$element.css({ | |
left: -(this._$element[0].offsetWidth / 2), | |
// По какой-то причине prettier и stylelint считают строку ниже за CSS | |
// stylelint-disable | |
top: -( | |
this._$element[0].offsetHeight + | |
this._$element.find('.ymap-popover-arrow')[0].offsetHeight | |
), | |
}); | |
}, | |
// Закрываем балун при клике на крестик, кидая событие "userclose" на макете | |
onCloseClick(e) { | |
e.preventDefault(); | |
this.events.fire('userclose'); | |
}, | |
// Используется для автопозиционирования (balloonAutoPan) | |
getShape() { | |
if (!this._isElement(this._$element)) { | |
return CustomBalloonLayout.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('.ymap-popover-arrow')[0].offsetHeight, | |
], | |
]), | |
); | |
}, | |
_isElement(element) { | |
return element && element[0] && element.find('.ymap-popover-arrow')[0]; | |
}, | |
}, | |
); | |
const CustomBalloonContentLayout = ymaps.templateLayoutFactory.createClass( | |
'<h3 class="popover-title">$[properties.balloonHeader]</h3>' + | |
'<div class="popover-content">$[properties.balloonContent]</div>', | |
); | |
coords.forEach((item, i) => { | |
geoObjects[i] = new ymaps.GeoObject( | |
{ | |
geometry: { | |
type: 'Point', | |
coordinates: coords[i], | |
}, | |
properties: { | |
balloonHeader: 'Заголовок балуна', | |
balloonContent: 'Контент балуна', | |
}, | |
}, | |
{ | |
// Указываем тип макета | |
iconLayout: 'default#imageWithContent', | |
// Добавляем своё изображение иконки метки | |
iconImageHref: 'img/marker.svg', | |
// Указываем размеры метки | |
iconImageSize: [50, 50], | |
// Изменяем положение левого верхнего угла иконки относительно её точки привязки | |
iconImageOffset: [-25, -25], | |
// Не скрывать метку при открытии балуна | |
hideIconOnBalloonOpen: false, | |
balloonShadow: false, | |
balloonLayout: CustomBalloonLayout, | |
balloonContentLayout: CustomBalloonContentLayout, | |
balloonPanelMaxMapArea: 0, | |
}, | |
); | |
}); | |
const clusterer = new ymaps.Clusterer({ | |
gridSize: 32, | |
clusterIconLayout: cluster.createCluster(), | |
clusterIconShape: cluster.createIconShape(), | |
}); | |
clusterer.add(geoObjects); | |
map.geoObjects.add(clusterer); | |
}; | |
ymaps.ready(init); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment